"use strict";
/*JM框架
REV:6.0
*/
console.log("123465465");
//js原生对象扩展,可以放到单独文件中
(function(){
//检查对象是否为空
Object.prototype.isEmpty=function(){
    for(var key in this) {
        if (this.hasOwnProperty(key)) {
            return false;
        }
    }
    return true;
}
//对象遍历,不包括继承属性
Object.prototype.each=function(fn,_this) {
    var key = void 0,
        result = void 0;
	if(!_this){
		_this=this;
	}	
    for (key in this){
        if (this.hasOwnProperty(key)) {
            result = fn.call(_this, key, this[key]);
            if (result === false) {                
                //break;
                return false;
            }
        }
    }
    return true;
};  
Object.prototype.del=function(id){
    delete(this[id]);
}
Array.prototype.__type__ = 'Array';
// 数组遍历
Array.prototype.each=function(fn,_this) {
    var i = void 0,
        key = void 0,
        result = void 0;
    if(!_this){
		_this=this;
	} 
    var length = this.length || 0;
    if(length>5000){
        console.warn('遍历超大型数组，请考虑优化!',this);
    }
    if(length>50000){
        //如果是超大型数组要小心，比如某些本来是object的因为index是数字，被误处理成了数组。
        //所以这里对非常大的数组采用for in来遍历
        for (key in this){
            if (this.hasOwnProperty(key)) {
                if(key=='length'){
                    continue;
                }
                result = fn.call(_this, key, this[key]);
                if (result === false) {                
                    //break;
                    return false;
                }
            }
        }
    }else{
        for (i = 0; i < length; i++) {
            if(this[i]===undefined){
                continue;
            }
            result = fn.call(_this, i, this[i]);
            if (result === false){
                //break;
                return false;
            }
        }
    }
    return true;
};
Array.prototype.del=function(id){
    //delete(this[id]);
    return this.splice(id,1);
}
HTMLCollection.prototype.each=function(fn,_this) {
    var i = void 0,
        key = void 0,
        result = void 0;
    if(!_this){
		_this=this;
	} 
    var length = this.length || 0;
    for (i = 0; i < length; i++) {
        if(this[i]===undefined){
            continue;
        }
        result = fn.call(_this, i, this[i]);
        if (result === false){
            //break;
            return false;
        }
    }
    return true;
}
Object.prototype.__type__='Object'
Boolean.prototype.__type__='Boolean'
FileList.prototype.__type__ = 'FileList';
File.prototype.__type__ = 'File';
Blob.prototype.__type__ = 'Blob';
FormData.prototype.__type__ = 'FormData';
Date.prototype.__type__ = 'Date';
Image.prototype.__type__ = 'Image';
//文件列表数组遍历
FileList.prototype.each=function(fn,_this){
    var i = void 0,
        item = void 0,
        result = void 0;
    if(!_this){
		_this=this;
	} 
    var length = this.length || 0;
    for (i = 0; i < length; i++) {
        if(this[i]===undefined){
            continue;
        }
        result = fn.call(_this, i, this[i]);
        if (result === false){
            //break;
            return false;
        }
    }
    return true;
}

String.prototype.__type__='String';
//去掉前后空格
String.prototype.Trim=function(r){ 
    return this.Ltrim(r).Rtrim(r);  
} ;
//去掉左边的空白  
String.prototype.Ltrim=function(r){  
    if(!r){
        r = " \t\n\r\b\f\u00A0";
    }
    var whitespace = new String(r);  
    var str = this.toString();  
    if (whitespace.indexOf(str.charAt(0)) != -1) {  
        var j=0, i = str.length;  
        while (j < i && whitespace.indexOf(str.charAt(j)) != -1){  
            j++;  
        }  
        str = str.substring(j, i);  
    }  
    return str;  
},      

//去掉右边空白  
String.prototype.Rtrim=function(r){  
    if(!r){
        r = " \t\n\r\b\f\u00A0";
    }
    var whitespace = new String(r);  
    var str = this.toString();  
    if (whitespace.indexOf(str.charAt(str.length-1)) != -1){  
        var i = str.length - 1;  
        while (i >= 0 && whitespace.indexOf(str.charAt(i)) != -1){  
            i--;  
        }  
        str = str.substring(0, i+1);  
    }  
    return str;  
} ,
//去掉左边char_list列出的字符之前的部分
String.prototype.LtrimTo=function(char_list){
    if(!char_list){
        char_list = " \t\n\r";
    }
    var whitespace = new String(char_list);  
    //var str = this;  
    var j=0, len = this.length; 
    while (j < len && whitespace.indexOf(this.charAt(j)) == -1){  
        j++;  
    }
    return this.substring(j+1,len);
}	
//去掉右边char_list列出的字符之后的部分
String.prototype.RtrimTo=function(r){
    if(!r){
        r = " \t\n\r";
    }
    var whitespace = new String(r);  
    //var str = this;  
    var i = this.length-1; 
    while (i >= 0 && whitespace.indexOf(this.charAt(i)) == -1){  
        i--;  
    }
    return this.substring(0,i);
}	
//字符串遍历
String.prototype.each = function(fn,_this){
    if(!_this){
		_this=this;
	} 
    for(var i=0,len=this.length;i<len;i++){
        if(false===fn.call(this,i,this.charAt(i))){
            return false;
        }
    }
    return true;
}
if(!String.prototype.startsWith){
    String.prototype.startsWith = function(str){
        try{
        var s = this.substr(0,str.length);
        if(s===str){
            return true;
        }else{
            return false;
        }
        }catch(e){
            return false;
        }
    }
}
if(!String.prototype.endsWith){
    String.prototype.endsWith = function(str){
        try{
        var s = this.substr(this.length-str.length);
        if(s===str){
            return true;
        }else{
            return false;
        }
        }catch(e){
            return false;
        }
    }
}
//Node对象扩展
//
//为了方便判断类型是否是文档节点，这里加入一个type，方便判断
Node.prototype.__type__ = 'Node';
/*测试class组合是否存在
className为要测试的class类，空格分割为同时有对应class类时返回true，逗号分割为任意一个条件满足返回true
同时存在逗号和空格分割时，先用逗号分开，把逗号分开的每一个当成一个整体，然后在看是否有空格分割
eg：
Node节点domA的html为<div class="classA">  domA.hassClass(“classA,classB classC” ) == true;
Node节点domB的html为<div class="classB classC">  domA.hassClass(“classA,classB classC” ) == true;
Node节点domB的html为<div class="classB">  domA.hassClass(“classA,classB classC” ) == false;
Node节点domB的html为<div class="classD">  domA.hassClass(“classA,classB classC” ) == false;
*/
Node.prototype.hasClass=function(className){
    if(typeof(className)=='string'){
        className=className.Trim();
        if(this.classList.contains(className)){
            return true;
        }
        className=className.split(',');
        className.each(function(k,v){
            if(!v){
                delete(className[k]);
            }
            className[k]=v.Trim().split(' ');
            className[k].each(function(i,s){
                if(!s){
                    delete(className[k][i]);
                }
            });
        });
    }else if(typeof(className)!='object'){   
        return false;
    }
    var _this=this;
    if(className.each(function(i,clist){                
        if(clist.each(function(k,v){
            if(!_this.classList || !_this.classList.contains(v)){
                return false;
            }
        })!==false){
            return false;
        };
    })===false){
        return true;
    }else{
        return false;
    };
}
/*添加class  
允许空格分割的多个class同时添加
eg：Node节点domA的html为<div class="classA">  d
    omA.addClass(“classB classC” )  后，html为：<div class="classA classB classC">
*/
Node.prototype.addClass=function(className){
    if(className===false){
        className='false';
    }
	if(!className){
		return;
	}  
    className=className.Trim();
	if(!className){
		return;
	}
    className=className.split(' ');
    var _this=this;
    className.each(function(k,v){
        v=v.Trim();
        if(!v){
            return;
        }
        _this.classList.add(v);
    });
};
/*移除class  
允许空格和逗号分割的多个class同时移除
eg：Node节点domA的html为<div class="classA classB classC">  
    domA.addClass(“classB classC” )或者domA.addClass(“classB,classC” ) 后，html为：<div class="classA">
*/
Node.prototype.removeClass=function(className){
	if(!className){
		return;
	}
    className=className.Trim();
	if(!className){
		return;
	}
    className=className.split('/,|\s/');
    var _this=this;
    className.each(function(k,v){
		if(!v){
			return;
		}
        v=v.Trim();
        if(!v){
            return;
        }
        this.classList.remove(v);
    },this);
};
/*遍历父节点，以每个父节点调用fn回调，直到父节点匹配到className；如果到body都没有匹配的className就返回null. 
没有找到会再遍历到body截至，所以不可用在html标签上设置class并用这个方法去查询
如果fn回调返回false，那么将停止遍历，并返回当前遍历位置的节点
className允许逗号(或运算)或空格（与运算）分隔的多个类
eg:
*/
Node.prototype.eachFather=function(className,fn,_this){
    if(typeof(className)=='function'){
        _this = fn;
        fn=className;
        className=false;
    }
    if(typeof(fn)!='function'){
        return null;
    } 
    if(!_this){
        _this=this;
    }
    if(className && typeof(className)!='string'){
        return null;
    }
    if(typeof(fn)!='function'){
        return null;
    }    
    if(className && typeof(className)=='string'){
        className=className.Trim().split(',');
        className.each(function(k,v){
            if(!v){
                delete(className[k]);
            }
            className[k]=v.Trim().split(' ');
            className[k].each(function(i,s){
                if(!s){
                    delete(className[k][i]);
                }
            });
        });
    } 
    //fn.apply(null,[]);
    var _dom=this;
    if(className){
        while(_dom  && _dom.nodeName!='BODY'){
            if(_dom.hasClass(className) && typeof(fn)=='function' && fn.call(_this,_dom)===false){
                return _dom;
            }
            _dom = _dom.parentNode || _dom.parentElement;    
        }
    }else{
        if(typeof(fn)!='function'){
            return null;
        }
        while(_dom  && _dom.nodeName!='BODY'){
            if(typeof(fn)=='function' && fn.call(_this,_dom)===false){
                return _dom;
            }
            _dom = _dom.parentNode || _dom.parentElement;    
        }
    }
    return null;
};
//定义只读的faterDom属性，指向父节点
Object.defineProperty(Node.prototype,'faterDom',{
    enumerable: false,
    get:function(){
        return this.parentNode || this.parentElement; 
    }
});
Node.prototype.eachBrother=function(className,fn,_this){
    if(typeof(className)=='function'){
        _this = fn;
        fn=className;
        className=false;
    }
    if(typeof(fn)!='function'){
        return false;
    } 
    if(!_this){
        _this=this;
    }
    if(typeof(className)=='string'){
        className=className.Trim().split(',');
        className.each(function(k,v){
            if(!v){
                delete(className[k]);
            }
            className[k]=v.Trim().split(' ');
            className[k].each(function(i,s){
                if(!s){
                    delete(className[k][i]);
                }
            });
        });
    }      

    if(className){
        this.faterDom.childNodes.each(function(i,v){   
            if(!v || (v.nodeType==3 && !v.textContent.Trim())){
                return;
            }
            if(v.hasClass(className) && (fn.call(_this,v)===false)){
                return false;
            }
        },this);
    }else{
        this.faterDom.childNodes.each(function(i,v){
            if(!v || v.nodeType==8 || (v.nodeType==3 && !v.textContent.Trim())){
                return;
            }
            if(fn.call(_this,v)===false){
                return false;
            }
        },this);
    }
}
/*将当前节点插入到指定位置,box是querySelectorAll方法支持的选择器 
*/
Node.prototype.appendTo=function(box){
    var boxdom = box;
    if(box.__type__!='Node'){
        boxdom=document.querySelector(box);
    }
    boxdom.appendChild(this);
    return boxdom;
};
Node.prototype.append2=function(html){
    //console.log(html);
    var newDiv;
    //var reg=/^HTML[A-Za-z]*Element$/i;
    if(!html){
        return;
    }else if(typeof(html)=='object' && html.__type__=='Node'){
        newDiv=html;
    }else if(typeof(html)=='string'){
        newDiv=document.createElement("div");
        newDiv.resetChildren(html);
        if(newDiv.children.length==1){
            newDiv = newDiv.children[0];
        }
    }else{
        return;
    }
    this.appendChild(newDiv);   
    return newDiv;
};
Node.prototype.appendBefor=function(dom){
    //获得父节点的引用
    var parentDiv = this.parentNode;
    //在DOM中在sp2之前插入一个新元素
    return parentDiv.insertBefore(dom, this);
};
Node.prototype.appendToBefor=function(dom){
    //获得父节点的引用
    var parentDiv = dom.parentNode;
    //在DOM中在sp2之前插入一个新元素
    return parentDiv.insertBefore(this, dom);
};

/*if(!Node.prototype.append){
    Node.prototype.append=function(newDiv){
        return this.appendChild(newDiv);
    }
}*/
/*遍历子节点，如果没有通过className指定遍历的条件，那么遍历所有只节点
如果fn回调返回false，那么将停止遍历当前元素的子节点不再递归，但是兄弟节点不受影响任然会遍历
eg:
*/
Node.prototype.eachChildren=function(className,fn,_this){
    if(typeof(className)=='function'){
        _this = fn;
        fn=className;
        className=false;
    }
    if(typeof(fn)!='function'){
        return false;
    } 
    if(!_this){
        _this=this;
    }
    if(typeof(className)=='string'){
        className=className.Trim().split(',');
        className.each(function(k,v){
            if(!v){
                delete(className[k]);
            }
            className[k]=v.Trim().split(' ');
            className[k].each(function(i,s){
                if(!s){
                    delete(className[k][i]);
                }
            });
        });
    }      
    if(className){
        this.childNodes.each(function(i,v){   
            if(!v || v.nodeType==8 || (v.nodeType==3 && !v.textContent.Trim())){
                return;
            }
            if(v.hasClass(className) && (fn.call(_this,v)===false)){
                return;
            }
            if(v.childNodes.length>0){
                v.eachChildren(className,fn,_this);
            }
        },this);
    }else{
        this.childNodes.each(function(i,v){
            if(!v || v.nodeType==8 || (v.nodeType==3 && !v.textContent.Trim())){
                return;
            }
            if(fn.call(_this,v)===false){
                return;
            }
            if(v.childNodes.length>0){
                v.eachChildren(className,fn,_this);
            }
        },this);
    }
};
//重新设置标签内部内容
Node.prototype.resetChildren = function(html){
    //var reg=/^HTML[A-Za-z]*Element$/i;
    if(typeof(html)=='object'&&html.__type__=='Node'){
        //html=html.outerHTML;
        this.children.each(function(i,v){
            v.remove();
            return false;
        });
        this.innerHTML='';
        this.appendChild(html);
    }else if(typeof(html)=='string'){
        this.innerHTML=html;
    }
    return this;
}

/*读取表单元素的输入内容
*/
Node.prototype.getVal=function(){
    var utype=this.getAttribute('utype');
    var type = this.nodeName;
    var value = null;
    if(type=='SELECT'){
        value=this.value;
        type='enum';
    }else if(type=='INPUT'){
        type = this.getAttribute('type');
        if(type=='radio'){
            if(this.checked){
                value=this.value;
            }else{
                value=null;
            }
            type='radio';
        }else if(type=='checkbox'){
            if(this.value!='on'){
                type = 'checkList';
                value = this.value;
            }else{
                value=this.checked;
                type='bool';
            }
        }else if(type=='file'){
            value=this.files;
            var multiple=this.getAttribute('multiple');
            //console.log(multiple);
            /* if(multiple===null){
                value
            }else{
                value.fullname=this.value;
            } */
            value.each(function(i,f){
                var name=f.name.split('.');
                name=name[name.length-1];
                f.lastName=name.toLocaleLowerCase();
            });
            value.fullname=this.value;
            if(multiple===null||multiple==="false"||multiple===false){
                type='file';
                value = value[0];
            }else{
                type='files';
            }
        }else{
            value=this.value.Trim();
            type='text';
        }            
    }else if(type=='TEXTAREA'){
        //console.log(this.value);
        value=this.value.Trim();
        type='text';
    }else{
        if(this.hasClass('inputBool')){
            if(this.hasClass('checked')){
                value=true;
            }else{
                value=false;
            }
            type='bool';
        }else if(this.hasClass('inputHtml')){
            value = this.innerHTML.Trim();
            type='html';
        }else if(utype=="QRcode"||utype=='qrcode'){
            value = this.QRtext;
            type = 'text';
            utype = false;
        }else{
            value = this.innerText.Trim();
            type='text';
        }
    }
    if(!utype){
        //return value;
        return {
            type:type,
            value:value,
            error:false,
            //name:this.getAttribute('name'),
            //data:this.getAttribute('data')
        }
    }
    type=utype;
    var notspace=this.getAttribute('notspace');
    notspace=notspace===null?false:true;
    var err=false;
    if(type=='bool'){
        if(typeof(value)=='string'){
            err='类型错误';
        }
    }else if(notspace && !value){
        err="不能为空";
    }else if(type=='checkList'){
        
    }else if(type=='varname'){
        var reg=/^[A-Za-z0-9_\.\-]+$/;
        if(value && !reg.test(value)){
            err='只能是字母数字下划线组合';
        }
        if(!value){
            value='';
        }
    }else if(type=='int'){
        if(!value){
            value=0;
        }
        var nv=parseInt(value);
        //var reg=/^[0-9]+$/i;
        if(nv!=nv){
            err='只能是数字';
            nv=0;
        }
        value=nv;
    }else if(type=='float'){
        if(!value){
            value=0;
        }
        var nv=parseFloat(value); 
        //var reg=/^[0-9]+(\.[0-9]+)?$/i;
        if(nv!=nv){
            err='只能是数字';
            nv=0;
        }
        value=nv;
    }else if(type=='float2'){
        if(!value){
            value=0;
        }
        var nv=parseFloat(value);
        //var reg=/^[0-9]+(\.[0-9][0-9]?)?$/i
        if(nv!=nv){
            err='只能是数字';
        }
        if(nv>0){
            value=parseInt(nv*100+0.5);
        }else{
            value=parseInt(nv*100-0.5);
        }
    }else if(type=='float4'){
        if(!value){
            value=0;
        }
        var nv=parseFloat(value);
        //var reg=/^[0-9]+(\.[0-9]{0:4})?$/i;
        if(nv!=nv){
            err='只能是数字';
        }
        if(nv>0){
            value=parseInt(nv*10000+0.5);
        }else{
            value=parseInt(nv*10000-0.5);
        }
    }else if(type=='email'){
        var reg = /^(\w+([._\-\w]*\w+)*)@(\w+([_\-]*\w+)*(.\w+([_\-]*\w+)*)+)$/i;
        if(value && !reg.test(value)){
            err='请填写正确的邮箱地址';
        }
        if(!value){
            value='';
        }
    }else if(type=='mobile'){
        var reg=/^1(3|4|5|7|8|9)[0-9]{9}$/i;
        if(value && !reg.test(value)){
            err='请输入正确的手机号';
        }  
        if(!value){
            value='';
        }    
    }else if(type=='html'){
        value=this.FilterXss(value);
    }else if(type.substr(0,9)=='dateTime:'){ 
        value=J4.Time(value);
        var now=J4.Time();
        var v=type.substr(9);
        v=v.split(',');
        if(v[1]){
            v=v[0];
        }else{
            v='94608000';
        }
        v=v.split('-');
		if(!parseInt(v[0])){
			v=[94608000,94608000];
		}
        var err=false;
        if(v[1] && (value<(v[0]*1) || value>(v[1]*1))){
            err='时间不正确';
        }else if(!v[1] && (value<now-v[0] || value>now+(v[0]*1))){
            err='时间不正确';
        }
        type = 'time';
    }else if(type.substr(0,5)=='file:'){
        var v=type.substr(5);
        v=v.split(',');
        err='';
        if(false!==value.each(function(i,v){
            if(v.size==0 || typelist.indexOf(v.lastName)==-1){
                err += v.name+':不支持的文件类型;'; 
            }
        },this)){
            err = false;
        }
        type = 'file';
    }
    return {
        type:type,
        value:value,
        error:err,
        //name:this.getAttribute('name'),
        //data:this.getAttribute('data')
    };
}
/*设置表单元素的输入内容
*/
Node.prototype.setVal=function(val){
    if(val===undefined||val===null || val!==val){
        val="";
    }
    var type=this.getAttribute('utype');
    if(type=='int'){
        val=parseInt(val*1+0.5);
        //console.log(this,val);
        if(!val){
            val='0';
        }
    }else if(type=='float'){
        val=parseFloat(val);
        //val=val/100;
        //val=val.toFixed(1);
    }else if(type=='float2'){
        val=val/100;
        val=val.toFixed(2);
    }else if(type=='float4'){
        val=val/10000;
        val=val.toFixed(4);
    }else if(type=='rmb_big'){
        val=J4.TurnToBIG(val/100);
    }else if(type=="QRcode"||type=='qrcode'){
        if(this.QRtext == val){
            return this;
        }
        this.QRtext = val;
        if(!this.QRobj){
            this.QRcfg = {
                width : this.getAttribute("qr-width"), 
                height : this.getAttribute("qr-heigh"), 
                typeNumber : 4,
                colorDark : this.getAttribute("qr-colorDark"), 
                colorLight : this.getAttribute("qr-colorLigh"), 
                text:val,
                correctLevel:1,// {L:1,M:0,Q:3,H:2};
            };
            if(!this.QRcfg.width){
                this.QRcfg.width = 256;
            }
            if(!this.QRcfg.height){
                this.QRcfg.height = this.QRcfg.width;
            }
            if(!this.QRcfg.colorDark){
                this.QRcfg.colorDark = "#000000";
            }
            if(!this.QRcfg.colorLight){
                this.QRcfg.colorLight = "#ffffff";
            }
        }
        if(window.QRCode){
            if(!this.QRobj){
                this.QRobj = new QRCode(this, this.QRcfg);
            }else{
                this.QRobj.clear();
                this.QRobj.makeCode(val);
            }
        }else{
            var dom = this;
            J4.Require("/share/js/qrcode/qrcode.js",function(){
                if(!dom.QRobj){
                    dom.QRobj = new QRCode(dom, dom.QRcfg);
                }else{
                    dom.QRobj.clear();
                    dom.QRobj.makeCode(val);
                }
            });
        }
        return this;
    }else if(typeof(type)=='string' && type.substr(0,9)=='dateTime:'){ 
        var v=type.substr(9);
        v=v.split(',');
		if(!parseInt(v[0])){
			v=v[0];
		}else{
			v=v[1];
		}
        if(val && val!='0'){
            //console.log(v,val,J4.Date(v,val));
            val=J4.Date(v,val);
        }else{
            val='';
        }
    }
    
    type=this.nodeName;
    //console.log(type,val);
    if(type=='SELECT'){
        this.value=val;
        this.setdValue = val;
        /*if(!this.onchange){
            this.onchange = function(){
                this.setdValue = this.value;
            }
        }*/
        if(!this.bindAttr['list'] && this.value!=val && this.childElementCount>0 && val!=='0' && val){
            //console.log(this.outerHTML);
            console.error('对SELECT设置的值无效',val,this.cloneNode(true));
        }
    }else if(type=='INPUT'){
        type = this.getAttribute('type');
        if(type=='radio'){
            this.checked=(val==this.value)?true:false;
        }else if(type=='checkbox'){
            //console.log(this.getAttribute('name'),val);
            //this.value=val;
            if(this.value=='on'){
                this.checked=val?true:false;
            }else{
                if(value && typeof(value)=='object'){
                    var name = this.getAttribute('name');
                    if(name){
                        value = value[name];
                    }else{
                        name = false;
                        value.each(function(i,v){
                            if(v==this.value){
                                value = v;
                                return false;
                            }
                        });
                    }
                }
                if(this.value==val){
                    this.checked = true;
                }else{
                    this.checked = false;
                }
            }
        }else if(type=='file'){
            if(val){
                try{
                    this.files=val;
                }catch(e){/* console.error(e) */};
                //this.value="aa";val.fullname || val.name || 'file';
            }else{
                //this.files=null;
                this.value='';
                //console.error(this.files);
            }
        }else{
            //console.log(this,val,this.value);
            if(val!=this.value){
                this.value=val;
            }
        }            
    }else if(type=='TEXTAREA'){
		//console.error(val);
        if(val!=this.value){
            this.value=val;
        }
    }else if(type=='OPTION'){
        this.value = val;
    }else{
        if(this.hasClass('inputBool')){
            if(val){
                this.addClass('checked');
            }else{
                this.removeClass('checked');
            }
        }else if(this.hasClass('inputHtml')){
            var a = this.innerHTML;
            if(a!=val){
                this.innerHTML=val;
            }
        }else{
            var a = this.innerText;
            if(a!=val){
                this.innerText=val;
            }
        }
    }
    return this;
}
//节点的显示和隐藏
Node.prototype.show=function(){
    this.removeClass('hidden');
    this.removeClass('hide');
    this.addClass('show');
}
Node.prototype.hide=function(fn){
    this.addClass('hidden');
    this.removeClass('show');
}
if(!Node.prototype.remove){
    Node.prototype.remove=function(){
        this.removeNode(true);
    }
}
Event.prototype.eachNode=function(className,fn,_this){
    var target = this.target || this.srcElement;
    if(!target || !target.eachFather){
        return;
    }
    target.eachFather(className,fn,_this);
}
if(!Function.prototype.bind){
    Function.prototype.bind = function(_this){
        var self = this;
        return function(){
            self.apply(_this,arguments);
        }
    }
}
Object.defineProperty(Object.prototype,'isEmpty',{
    enumerable: false
});
Object.defineProperty(Object.prototype,'each',{
    enumerable: false
});
Object.defineProperty(Object.prototype,'__type__',{
    enumerable: false
});
Object.defineProperty(Object.prototype,'del',{
    enumerable: false
});
Object.defineProperty(Array.prototype,'del',{
    enumerable: false
});
Object.defineProperty(Array.prototype,'each',{
    enumerable: false
});
Object.defineProperty(Array.prototype,'__type__',{
    enumerable: false
});
Object.defineProperty(FileList.prototype,'each',{
    enumerable: false
});
Object.defineProperty(FileList.prototype,'__type__',{
    enumerable: false
});
Object.defineProperty(HTMLCollection.prototype,'each',{
    enumerable: false
});
})();

(function(){
var baseUrl = window.location.href;
if(baseUrl.startsWith('https://')){
    baseUrl = 'https://'+window.location.host;
}else{
    baseUrl = 'http://'+window.location.host;
}
var _srcBasePath = '/src/';
var _apiBasePath = '/';
var _ServerRev = Math.round(new Date().getTime()/1000);
var _Debug = true;
var _fullWindow = false;
var J4 = {
    __type__:'J4',//用来判断是否是J4对象
    REV:'6.0',//版本号
    set ServerRev(v){//服务器版本标识，用来标识资源是否更新
        _ServerRev = v;
    },
    get ServerRev(){
        return _ServerRev;
    },
    set srcBasePath(url){
       _srcBasePath = url;     
    },
    get srcBasePath(){
       return _srcBasePath;     
    },
    set apiBasePath(url){
       _apiBasePath = url;     
    },
    get apiBasePath(){
       return _apiBasePath;     
    },
    set DEBUG(v){
        _Debug = v;
    },
    get DEBUG(){
        return _Debug;
    },
    _ready:false,
    floatwindow:false,
    ready:function(fn){
        if(typeof(fn)=='string'){
            J4.ready(function(){
                J4.Require(fn,function(mod){
                    mod.create();
                });
            });
            return;
        }
        if(typeof(fn)!='function'){
            return;
        }
        if(J4._ready){
            fn.call(J4);
        }else{
            J4.event('onload').once(fn);
        }
    },
    //J4配置数据
    CFG:{
        online:true,  
        LoaddingIMGURL:'/src/share/img/loadding.gif',
        //LoaddingIMGURL:"/core/img/loadding.gif",
        upMaxsize:50,//允许上传的文件大小，单位MB
        upfiletype:['gif','png','jpg','rar','zip','7z','xls',
            'xlsx','csv','txt','pdf','docx','html',    
            'doc','dra','pcb','brd'],      
    },
    //id生成器，每调用一次返回一个本页唯一字符串
    GetOnlyId:(function(){
        var oid = 0;
        return function(){
            oid++;
            return 'oid'+oid;
        }
    })(),   
    // 获取unix时间戳(秒)  ，该函数没有测试参数错误的情况，参数错误可能会出现不可忽略错误
    Time:function(date){
        if(typeof(date)=='undefined'){
            date=new Date();
        }else if(typeof(date)=='string'){
            date=date.replace(new RegExp(/-/gm) ,"/"); 　　//将所有的'-'转为'/'即可
            date=new Date(date);
        }
        if(typeof(date)!='object' || date.__type__!='Date'){
            console.error('非法时间:',date);
            date = new Date();
        }
        return Math.round(date.getTime()/1000);
    },
    //获取当前时间毫秒
    mTime:function(){
        var date = new Date();
        date = date.getTime();
        //console.log(date);
        return date;
    },
    /*获取指定格式的时间，目前支持 yyyy,yy,mm,m,dd,d,hh,h,ii,i,ss,s替换
    其他format=='toNow',则返回
    */
    Date:function(format,utime){
        if(!format){
            format='yyyy-mm-dd hh:ii:ss';
        }
        var unixTimestamp;
        //console.log(utime);
        var reg=/^[0-9]+$/i;
        if(typeof(utime)=='string' && reg.test(utime)){
            utime=parseInt(utime);
        }
        if(typeof(utime)=='string'){
			utime = J4.Time(utime);
			unixTimestamp = new Date( utime* 1000); 
		}else if(utime && typeof(utime)=='object' && utime.__type__=='Date'){
			unixTimestamp = utime;
			utime=Math.round(utime.getTime()/1000);
		}else if(utime){
            unixTimestamp = new Date( utime* 1000); 
        }else{
            unixTimestamp = new Date(); 
			utime=Math.round(unixTimestamp.getTime()/1000);
        }
		var year=unixTimestamp.getFullYear();
		var month=unixTimestamp.getMonth() + 1;
		var data=unixTimestamp.getDate();
		var hours=unixTimestamp.getHours();
		var minutes=unixTimestamp.getMinutes();
		var seconds=unixTimestamp.getSeconds();
        if(!data){
            return '';
        }
        if(typeof(format)!='string'){
            console.log('时间数据错误!');
            return;
        }
		if(format=='toNow'){
            var now = J4.Time(J4.Date("yyyy/mm/dd"));
            var utime2 = J4.Time(J4.Date("yyyy/mm/dd",utime));
			var xqs=['前天','昨天','今天','明天','后天'];
			var nowto = utime2-now;
            nowto = parseInt(nowto/60/60/24)+2;
            if(nowto>=0 && nowto<=4){
                return xqs[nowto];
            }else{
                now = new Date();               
                if(now.getFullYear()==year){
                    format='mm-dd';
                }else{
                    format='yyyy-mm-dd'; 
                }
            }
		}
        format=format.replace(/yyyy/g,year).replace(/yy/g,year%100);
        format=format.replace(/mm/g,month>=10?month:('0'+month).replace(/m/g,month));
        format=format.replace(/dd/g,data>=10?data:('0'+data).replace(/d/g,data));
        format=format.replace(/hh/g,hours>=10?hours:('0'+hours).replace(/h/g,hours));
        format=format.replace(/ii/g,minutes>=10?minutes:('0'+minutes).replace(/i/g,minutes));
        format=format.replace(/ss/g,seconds>=10?seconds:('0'+seconds).replace(/s/g,seconds));
        return format;
    },
    //转换为人民币大写
    TurnToBIG:function(n){    
        var fraction = ['角', '分'];    
        var digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];    
        var unit = [ ['元', '万', '亿'], ['', '拾', '佰', '仟']  ];    
        var head = n < 0? '欠': '';    
        n = Math.abs(n);    
        var s = '';    
        for (var i = 0; i < fraction.length; i++){    
            s += (digit[Math.floor(n * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '');    
        }    
        s = s || '整';    
        n = Math.floor(n);    
        for (var i = 0; i < unit[0].length && n > 0; i++)     {    
            var p = '';    
            for (var j = 0; j < unit[1].length && n > 0; j++)     {    
                p = digit[n % 10] + unit[1][j] + p;    
                n = Math.floor(n / 10);    
            }    
            s = p.replace(/(零.)*零$/, '').replace(/^$/, '零')  + unit[0][i] + s;    
        }    
        return head + s.replace(/(零.)*零元/, '元').replace(/(零.)+/g, '零').replace(/^整$/, '零元整');    
    }, 
    
    /*表达式计算器,str是要计算的表达式，data是表达式中的变量值 
    eg: Calc('a+b*2',{a:2,b:3}) 返回值是 8 即2+3*2
    该类方法有非常大的改进空间，下版本将使用面向对象思想提升计算效率
    */
    Calc:function(str,data){
        //console.log(str,data);
        if(str==='a'){//快速计算
            return data['a'];
        }
        return J4.ExpToFunction(str)(data);       
    },
    ExpToFunction:function(exp,start,end){
        if(typeof(exp)==='function'){
            return exp;
        }else if(typeof(exp)!='string'){
            console.error('表达式不是一个字符串');
            return function(){return undefined;};
        } 
        //exp = exp.Trim();
        if(exp==='a'){//快速计算
            var fn = function(data){return data.a;};
            //fn.len = 1;
            fn.srcCode = 'data.a';
            fn.exp = exp;//原始内容
            return fn;
        }
        //console.log(exp);
        var shendu = 0;
        var expStr = exp.split('');
        var str ='';
        if(!start){
            start = 0;
        }
        if(!end){
            end = expStr.length;
        }
        //console.log(index,end);
        var index=start;
        while(index<end){
            var i = index++;
            var c = expStr[i];
            switch(c){
                case '(':
                    shendu++;
                    str+=c;
                    break;
                case ')':
                    shendu--;
                    str+=c;
                    break;
                case ',':
                    if(shendu==0){
                        var fn = new Function( 'data' , 'return ('+str+')' );
                        fn.len = index;
                        fn.exp = exp.substring(start,end);//原始内容
                        return fn;
                    }
                case '{':
                case '}':                       
                case '!':
                case '+':
                case '-':
                case '*':
                case '/':
                case '%':
                case '>':
                case '<':
                case '=':
                case '&':
                case '|':
                case ':':
                case '?':
                case ';':
                case '[':
                case ']':
                case '.':
                case '0':    
                case '1':    
                case '2':    
                case '3':    
                case '4':    
                case '5':    
                case '6':    
                case '7':    
                case '8':    
                case '9':   
                    str+=c;//数字
                    break;
                case ' ':   
                case '\t':
                case '\r':
                case '\n':
                case '\f':
                case '\b':
                case '\u00A0':
                    str+=' ';//数字
                    break;
                case '"':   
                case "'":   
                    str+=c;//数字
                    while(index<end){
                        i = index++;
                        var c1 = expStr[i];
                        str+=c1;
                        if(c1==='\\'){
                            i = index++;
                            c1 = expStr[i];
                            str+=c1;
                        }else if(c1===c){
                            break;
                        }
                    }
                    break;
                default:
                    while(index<end){
                        var c1 = expStr[index];
                        var exit = false;
                        switch(c1){
                            case '(':
                            case '{':
                            case '[':
                            case ')':
                            case '}':                                  
                            case '!':
                            case '+':
                            case '-':
                            case '*':
                            case '/':
                            case '%':
                            case '>':
                            case '<':
                            case '=':
                            case '&':
                            case '|':
                            case ':':
                            case '?':
                            case ',':
                            case ';':
                            case ']':
                            case ' ':
                            case '\r':
                            case '\n':
                            case '\t':
                            case '\f':
                            case '\b':
                            case '\u00A0':
                                exit = true;
                                break;
                            default:
                                c+=c1;
                                index++;
                                break;
                        }
                        if(exit){
                            break;
                        }
                    }
                    c = c.Trim();
                    switch(c){
                        case 'true':
                        case 'TRUE':
                        case 'false':
                        case 'FALSE':
                        case 'null':
                        case 'NULL':
                        case 'undefined':
                            str+=' '+c+' ';
                            break;
                        default:
                            if(c=='$Int' || c=='$INT'){
                                str+=' parseInt';
                            }else if(c=='$Float'){ //float
                                str+=' parseFloat';
                            }else if(c.startsWith('$')){ //自定义公式
                                str+='this.'+c.substr(1);
                            }if(str.endsWith('.')){
                                str+=c;
                            }else{
                                str+='data.'+c;
                            }
                            break;
                    }
                    //console.log(c,index);
                    break;
            }
        }
        //console.log(str,expStr);
        //var fn = new Function( 'data' , 'try{ return ('+str+')}catch(e){console.log(e);console.log(data);}' );
        var fn = new Function( 'data' , 'try{ return ('+str+')}catch(e){}' );
        //fn.len = index;
        fn.srcCode = str;
        fn.exp = exp.substring(start,end);//原始内容
        return fn;
    },
    //json字符串转成object对象,失败返回null而不会触发错误
    Json_decode:function(str){
        if(typeof(str)=='object'){
            return str;
        }
        try{
            return JSON.parse(str);
        }catch(e){
            //console.error(e);
            return null;
        }
    },
    //object对象转成json字符串,转换会忽略掉方法和继承属性
    Json_encode:function(obj){
        return JSON.stringify(obj);
    },
    //对象复制(支持自定义BindArray类型,BindArray会被复制成普通类型),只复制本身属性而不包含方法和继承属性
    CopyObj:function(obj){
        if(!obj || typeof(obj)!='object'){
            return obj;
        }
        var rs;
        //console.log(obj.constructor.name,obj.__type__);
        if( obj.__type__=='FileList'){
            /* rs = [];
            obj.each(function(i,v){
                rs.push(v);
            }); */
            return obj;
        }else if(obj.__type__=='File'){
            return obj;
        }else if(Array.isArray(obj)){
            rs=[];
            //console.log(obj.length,obj);
            obj.each(function(i,v){
                if(v && typeof(v)=='function'){
                    return;
                }else if(v && typeof(v)=='object'){
                    rs.push(J4.CopyObj(v));
                }else{
                    rs.push(v);
                }
            });
        }else if(obj.__type__=="BindArray"){
            rs=[];
            obj.each(function(i,v){
                if(v && typeof(v)=='function'){
                    return;
                }else if(v && typeof(v)=='object'){
                    rs.push(J4.CopyObj(v));
                }else{
                    rs.push(v);
                }
            });
        }else{
            rs={};
            obj.each(function(i,v){
                if(v && typeof(v)=='function'){
                    return;
                }else if(v && typeof(v)=='object'){
                    rs[i]=J4.CopyObj(v);
                }else{
                    rs[i]=v;
                }
            });
        }
        return rs;
    },
    //用obj2更新obj1,subAll我true时，子对象也执行合并
    Merge:function(obj1,obj2,subAll){
        if(!obj1 || typeof(obj1)!='object'){
            obj1 = {};
        }
        if(!obj2 || typeof(obj2)!='object'){
            return obj1;
        }
        obj2.each(function(i,v){
            if(subAll && typeof(v)=='object'){
                if(!obj1[i]  || obj[i].__type__!='Object'){
                    obj2[i]={};
                }
                J4.Merge(obj1[i],v,subAll);
            }else{
                obj1[i]=v;
            }
        });
        return obj1;
    },
    //User-Agent处理   
    //检查是否是webkit类的浏览器
    CheckUAisWebkit:function(ua){
        var reg = /webkit/i;
        if(!ua){
            ua=navigator.userAgent;
        }
        return reg.test(ua);
    }, 
    //检查是否是 ie
    CheckIsIE:function(){
        return 'ActiveXObject' in window;
    }, 
    
    //空格转换为html空格
    StrSpaceToHtmlSpace: function(str){
        str=str.replace(/\r\n/g, "<br>");
        str=str.replace(/\t/g,"&nbsp;&nbsp;");
        str=str.replace(/\n/g,"<br>");
        str=str.replace(/\r/g,"<br>");
        str=str.replace(/$/g,"<br>");
        str=str.replace(/\s/g,"&nbsp;");	
        return str;
    },
    //xss过滤
    FilterXss:function(html,config){
        //return filterXSS(html,config);
        if(typeof(filterXSS)!='function'){
            console.error('没有加载xss.min.js');
        }
        return filterXSS(html,config?config:J4.xssConfig);
    },
    //创建一个事件对象
    Event:(function(){
        //事件对象
        function evobj(_this){         
            //this.name=name;
            this._this=_this;
            this.elist={};
            this.onceList={};
            this.regfn=false;
            this._enable=true;
        }
        evobj.prototype={
            //_enable:true,
            //regfn:false,
            //runcount:0,//记录正在运行的事件，对象remove时根据这个判断事件是否已经执行完成
            //na可以指定一个方法名字，也可以省略直接写匿名方法，下面相同
            on:function(na,cb,_this){
                if(typeof(na)=='string' 
                        && typeof(cb)!='function' 
                        && this.elist[na]){
                    delete this.elist[na];
                    return this;
                }
                if(typeof(na)=='function'){
                    _this = cb;
                    cb=na;
                    na=J4.GetOnlyId();
                }
                if(typeof(cb)!='function' || typeof(na)!='string'){
                    //console.error('注册事件错误',na,cb);
                    return;
                }
                if(na=='__reg'){
                    console.error('不允许注册事件的function名称为__reg');
                    return false;
                }  
                if(!_this){
                    _this = this._this;
                }
                cb._this = _this;
                this.elist[na]=cb;
                return this;
            },
            once:function(na,cb,_this){
                if(typeof(na)=='string' 
                        && typeof(cb)!='function' 
                        && this.onceList[na]){
                    delete this.onceList[na];
                    return this;
                }
                if(typeof(na)=='function'){
                    _this = cb;
                    cb=na;
                    na=J4.GetOnlyId();
                }
                if(typeof(na)!='string' || typeof(cb)!='function'){
                    console.error('注册事件错误',na,cb);
                    return;
                }
                if(!_this){
                    _this = this._this;
                }
                cb._this = _this;
                this.onceList[na]=cb;               
                return this;
            },
            //on的语法糖，注册一个特定的方法，重复注册时覆盖上一次注册,确保事件只有一个唯一的处理
            reg:function(fn,_this){
                if(fn){
                    if(typeof(fn)!='function'){
                        console.error('注册事件错误reg',fn);
                    }
                    if(!_this){
                        _this = this._this;
                    }
                    fn._this = _this;
                    //this.on('thisonce',fn);
                    this.regfn=fn;
                }else{
                    //this.off('thisonce');
                    return this.regfn;
                }
                return this;
            },            
            off:function(name){
                if(!name){
                    this.elist={};
                    this.onceList={};
                }else if(name=='__reg'){
                    this.regfn=false;
                }else{
                    if(this.elist[name]){
                        delete this.elist[name];
                    }
                    if(this.onceList[name]){
                        delete this.onceList[name];
                    }
                }
                return this;
            },
            enable:function(){
                //console.log('enable');
                this._enable=true;
                return this;
            },
            disable:function(){
                console.error('Event disable');
                this._enable=false;
            },
            /* run:function(){
                return this._run(arguments);
            }, */
            run:function(){
                if(!this._enable){
                    return true;
                }
                var argu = arguments;
                var rs=true;
                var temp;
                var fnListA={};
                var fnListB={};
                var reg;
                this.onceList.each(function(i,v){                  
                    fnListA[i]=v;
                });
                this.onceList={};
                if(this.elist){
                    this.elist.each(function(i,v){
                        fnListB[i]=v;
                    },this);
                }
                
                if(typeof(this.regfn)=='function'){
                    reg=this.regfn;
                }
                
                fnListA.each(function(i,v){                  
                    temp=v.apply(v._this,argu);
                    if(temp===false){
                        rs=false;
                    }
                },this);
                fnListB.each(function(i,v){
					this._this.__nofn=i;
                    temp=v.apply(v._this,argu);
                    if(temp===false){
                        rs=false;
                    }
                },this);
				this._this.__nofn=false;
                if(rs===false){
                    return rs;
                }
                if(typeof(reg)=='function'){
                    temp=reg.apply(reg._this,argu);
                    if(temp===false){
                        rs=false;
                    }
                }
                return rs;
            },           
            setThis:function(a){
                this._this=a;
                return this;
            },
            extend:function(obj){
                if(Object.assign){
                    Object.assign(this.elist,obj.elist);
                    Object.assign(this.onceList,obj.onceList);
                }else{
                    $.extend(this.elist,obj.elist);
                    $.extend(this.onceList,obj.onceList);
                }
                if(!this.regfn){
                    this.regfn=obj.regfn;
                }
            }
        };
    
        //由事件对象组成的事件组对象,实现一次注册或触发多个事件
        function evobjList(){
            this.eventList={};
        }
        evobjList.prototype={
            getEvent:function(name,_this){
                if(!name){
                    return this;
                }
                if(!_this){
                    _this=this._this;
                }
                if(!this.eventList[name]){
                    this.eventList[name]=new evobj(_this);
                    this.eventList[name].name=name;
					if(!_this.eventOffSelf){
						_this.eventOffSelf=function(){
							if(this.__nowEventName){
								this.__nowEventName.off(this.__nofn);
							}
						}
					}
                }
                return this.eventList[name];
            },
            event:function(obj,name){
                var _this=this;
                if(!name){
                    var fn=function(name){
                        if(!name){
                            return fn;
                        }else{
                            return new nowEvent(name,_this,obj);
                        }
                    };
                    fn.__type__='binddedEvent';     
                    fn.event=this;
                    return fn;
                }else if(typeof(name)=='object'){
                    return this.extend(name);
                }else if(typeof(name)=='string'){
                    return new nowEvent(name,_this,obj);
                }
            },
            extend:function(obj){
                if(!obj || typeof(obj.eventList)!='object'){
                    return this;
                } 
                for(var e in obj.eventList){
                    if(this.eventList[e]){
                        this.eventList[e].extend(obj.eventList[e]);
                    }else{
                        this.eventList[e]=obj.eventList[e];
                    }
                }
                return this;
            }			
        }
		//事件代理程序
		function nowEvent(name,elist,_this){
			if(!name){
                return this;
            }
			this._this=_this;
			this.elist=elist;
			this.nowList=name.split(',');
            /* this.nowList.each(function(k,v){
                if(!v){
                    delete(this.nowList[k]);
                    return;
                }
                console.log(v,);
                v=v.Trim();
                this.nowList[k]=v;
            }); */
		}
		nowEvent.prototype={
			on:function(na,cb,__this){
                //console.log(this.nowList);
				this.nowList.each(function(k,v){
                    //console.log(v);
					v=v.Trim();
					if(!v){
						return;
					}				
					this.elist.getEvent(v,this._this).on(na,cb,__this);
				},this);
				return this;
			},
			reg:function(fn,__this){
				this.nowList.each(function(k,v){
					v=v.Trim();
					if(!v){
						return;
					}				
					this.elist.getEvent(v,this._this).reg(fn,__this);
				},this);
				return this;
			},
			off:function(name){
				this.nowList.each(function(k,v){
					v=v.Trim();
					if(!v){
						return;
					}				
					this.elist.getEvent(v,this._this).off(name);
				},this);
				return this;
			},
			enable:function(){
				this.nowList.each(function(k,v){
					v=v.Trim();
					if(!v){
						return;
					}				
					this.elist.getEvent(v,this._this).enable();
				},this);
				return this;
			},
			disable:function(){
				this.nowList.each(function(k,v){
					v=v.Trim();
					if(!v){
						return;
					}				
					this.elist.getEvent(v,this._this).disable();
				},this);
				return this;
			},
			once:function(na,cb,__this){
				this.nowList.each(function(k,v){
					v=v.Trim();
					if(!v){
						return;
					}				
					this.elist.getEvent(v,this._this).once(na,cb,__this);
				},this);
				return this;
			},
			run:function(){
				return this.applyRun(arguments);
			},
			_run:function(argu){
                console.error('该方法从6.0版本开始不在支持');
                this.applyRun(argu);
			},
            applyRun:function(argu){
                //var argu = arguments;                
				var rs=true;	
                if(!this._this){
                    this._this = J4;
                }
				this.nowList.each(function(k,v){
					v=v.Trim();
					if(!v){
						return;
					}
					if(!this.elist.eventList[v]){
						return;
					}
					this._this.__nowEventName=this.elist.eventList[v];	
					if(this._this.__nowEventName.run.apply(this._this.__nowEventName,argu)===false){
						rs=false;
					};
				},this);
                this._this.__nowEventName=false;
				return rs;
            }
		};
		 
        //Event方法创建一个事件实例
        return function(_this){
            var evlistObj = new evobjList();
            if(_this){
                return evlistObj.event(_this);
            }
            //evlistObj是通过继承合并的事件列表
            //var evlistObj=new evobjList();
            //如果传入的是一个事件对象，那么将会合并
            var evfn=function(name){
                if(!name){                   
                    return evlistObj.event(this);
                }else{
					//name=name.split(',');
                    return evlistObj.event(this,name);
                    //return new nowEvent(name,evlistObj,this);
				}
            }
            evfn.__type__='event';           
            evfn.event=evlistObj;
            evfn.id=J4.GetOnlyId();
            //evfn.event.event.event=evfn.event;
            return evfn;
        }
    })(),
    
    /*按键区域管理栈：后注册的按键对象会覆盖前面的所有按键事件（不包括默认）,对象撤销后会全部恢复
    //var key=HotkeyEvent();//创建快捷键对象，覆盖之前用该方法创建的对象
    //key.event类型是J4.Event返回的事件对象,支持reg、run、once、on方法,默认有kd、kd_*（任意按键和特定按键事件）和kd_Enter、kd_Esc、kd_Tab、kd_Backspace、kd_F2,
    //key.event('kd').reg(function(keynumber){/*这里添加任意按键执行代码,keynumber是按键键码值* /});//注册任意按键按下执行代码
    //key.event('kd_keynumber').reg();//注册按键值是keynumber的按键执行代码
    //key.remove() //当不需要的时候使用它移除快捷键
    //全局快捷键代理:keydownEvent对象，全局有效
    //var keydownEvent;//当前生效的快捷键组
    */
    HotkeyEvent:(function(){
        //var defultKeydown=false;
        var kn=0,kevlist=[];
        var Shiftdown =false;
        var Ctrldown=false;
        var Altdown = false;
        kevlist[0]=false;//newEvent();
        function runKeyEvent(names,e){
            //console.log(e.keyCode);
            if(J4.plugRun){
                e.keyNames = names;
                return J4.plugRun.call(document,e);
            }
            var a = true;
            names.each(function(i,v){
                //console.log(v);
                if(J4.event(v).run(e.keyCode,e)===false){
                    a = false;
                    return false;
                }
            });
            return a;
        }
        /*浏览器原生方法*/
        document.onkeydown=function(event){
            var e = event || window.event || arguments.callee.caller.arguments[0];
            if(!e){
                return;
            }
            //console.log(e.keyCode);
            /* if(J4.data.disableUserEvent){//全局关闭
                if( e.keyCode!=116 && e.keyCode!=123){
                    return;// false;
                }else{
                    return;
                }
            } */
            
            var rs=true;
            if(e.keyCode==16){
                if(Shiftdown){
                    return;
                }
                Shiftdown=true;
                if(runKeyEvent(['onkeydown_shift','onkeydown_'+e.keyCode,'onkeydown'],e)===false){
                    return false;
                }
                if(kevlist[kn]){
                    if(kevlist[kn].event('kd_Shift').run(e.keyCode,e)===false){rs=false};
                    if(kevlist[kn].event('kd_'+e.keyCode).run(e.keyCode,e)===false){rs=false};
                }
                return rs;
            }
            if(e.keyCode==17){
                if(Ctrldown){
                    return;
                }
                Ctrldown=true;
                if(runKeyEvent(['onkeydown_ctrl','onkeydown_'+e.keyCode,'onkeydown'],e)===false){
                    return false;
                }
                if(kevlist[kn]){
                    if(kevlist[kn].event('kd_Ctrl').run(e.keyCode,e)===false){rs=false};
                    if(kevlist[kn].event('kd_'+e.keyCode).run(e.keyCode,e)===false){rs=false};
                }
                return rs;
            }
            if(e.keyCode==18){
                if(Altdown){
                    return;
                }
                Altdown=true;
                if(runKeyEvent(['onkeydown_Alt','onkeydown_'+e.keyCode,'onkeydown'],e)===false){
                    return false;
                }
                if(kevlist[kn]){
                    if(kevlist[kn].event('kd_Alt').run(e.keyCode,e)===false){rs=false};
                    if(kevlist[kn].event('kd_'+e.keyCode).run(e.keyCode,e)===false){rs=false};
                }
                return rs;
            }
            if(!(Shiftdown||Ctrldown||Altdown)){
                //console.log('a',e.keyCode);
                if(e.keyCode==27){ // 按 Esc 
                    if(runKeyEvent(['onkeydown_esc','onkeydown_'+e.keyCode,'onkeydown'],e)===false){
                        return false;
                    }
                    if(kevlist[kn] && kevlist[kn].event('kd_Esc').run(e.keyCode,e)===false){rs=false};
                }else if(e.keyCode==113){ // 按 F2 
                    if(runKeyEvent(['onkeydown_f2','onkeydown_'+e.keyCode,'onkeydown'],e)===false){
                        return false;
                    }
                    if(kevlist[kn] && kevlist[kn].event('kd_F2').run(e.keyCode,e)===false){rs=false};
                }else if(e.keyCode==13){ // enter 键
                    if(runKeyEvent(['onkeydown_f2','onkeydown_'+e.keyCode,'onkeydown'],e)===false){
                        return false;
                    }
                    if(kevlist[kn] && kevlist[kn].event('kd_Enter').run(e.keyCode,e)===false){rs=false};
                }else if(e.keyCode==8){ // bk 键
                    if(runKeyEvent(['onkeydown_backspace','onkeydown_'+e.keyCode,'onkeydown'],e)===false){
                        return false;
                    }
                    if(kevlist[kn] && kevlist[kn].event('kd_Backspace').run(e.keyCode,e)===false){rs=false};
                }else if(e.keyCode==9){ // tab 键
                    if(runKeyEvent(['onkeydown_tab','onkeydown_'+e.keyCode,'onkeydown'],e)===false){
                        return false;
                    }
                    if(kevlist[kn] && kevlist[kn].event('kd_Tab').run(e.keyCode,e)===false){rs=false};
                }else{
                    if(runKeyEvent(['onkeydown_'+e.keyCode,'onkeydown'],e)===false){
                        return false;
                    }
                }
                if(kevlist[kn] && kevlist[kn].event('kd_'+e.keyCode).run(e.keyCode,e)===false){rs=false};
                if(kevlist[kn] && kevlist[kn].event('kd').run(e.keyCode,e)==false){rs=false};
            }else if(Shiftdown&&(!Ctrldown)&&(!Altdown)){
                if(runKeyEvent(['onkeydown_shift_'+e.keyCode,'onkeydown'],e)===false){
                    return false;
                }
                if(kevlist[kn] && kevlist[kn].event('kd_shift_'+e.keyCode).run(e.keyCode,e)===false){rs=false};
                if(kevlist[kn] && kevlist[kn].event('kd_shift').run(e.keyCode,e)===false){rs=false};
            }else if((!Shiftdown)&&Ctrldown&&(!Altdown)){
                if(runKeyEvent(['onkeydown_ctrl_'+e.keyCode,'onkeydown'],e)===false){
                    return false;
                }
                if(kevlist[kn] && kevlist[kn].event('kd_ctrl_'+e.keyCode).run(e.keyCode,e)===false){rs=false};
                if(kevlist[kn] && kevlist[kn].event('kd_ctrl').run(e.keyCode,e)===false){rs=false};
            }else if((!Shiftdown)&&(!Ctrldown)&&Altdown){
                if(runKeyEvent(['onkeydown_alt_'+e.keyCode,'onkeydown'],e)===false){
                    return false;
                }
                if(kevlist[kn] && kevlist[kn].event('kd_alt_'+e.keyCode).run(e.keyCode,e)===false){rs=false};
                if(kevlist[kn] && kevlist[kn].event('kd_alt').run(e.keyCode,e)===false){rs=false};
            }
            //console.log('kd:',e.keyCode,kn,rs);
            return rs;
        };
        document.onkeyup=function(event){
            //if(J4.disableUserEvent)return false;//全局关闭
            var e = event || window.event || arguments.callee.caller.arguments[0];
            if(!e){
                return;
            }
            if(e.keyCode==16){
                Shiftdown=false;
            }
            if(e.keyCode==17){
                Ctrldown=false;
            }
            if(e.keyCode==18){
                Altdown=false;
            }
            var rs=true;
            if(kn==0){
                return;
            }
            //var _this=kevlist[kn]._this;
            //console.log(e.keyCode);
            
            if(e.keyCode==27){ // 按 Esc 
                if(runKeyEvent(['onkeyup_esc','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kup_Esc').run(e.keyCode,e)===false){rs=false};
            }else if(e.keyCode==113){ // 按 F2 
                if(runKeyEvent(['onkeyup_f2','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kup_F2').run(e.keyCode,e)===false){rs=false};
            }else if(e.keyCode==13){ // enter 键
                if(runKeyEvent(['onkeyup_enter','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kup_Enter').run(e.keyCode,e)===false){rs=false};
            }else if(e.keyCode==8){ // bk 键
                if(runKeyEvent(['onkeyup_backspace','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kup_Backspace').run(e.keyCode,e)===false){rs=false};
            }else if(e.keyCode==9){ // tab 键
                if(runKeyEvent(['onkeyup_tab','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kup_Tab').run(e.keyCode,e)===false){rs=false};
            }else if(e.keyCode==17){ // ctrl 键
                if(runKeyEvent(['onkeyup_ctrl','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kup_Ctrl').run(e.keyCode,e)===false){rs=false};
            }else{
                if(runKeyEvent(['onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
            }
            if(kevlist[kn].event('kup_'+e.keyCode).run(e.keyCode,e)===false){rs=false};
            if(kevlist[kn].event('kup').run(e.keyCode,e)===false){rs=false};
            //console.log('kup:',rs);
            return rs;
        };
        document.onkeypress=function(event){
            //if(J4.data.disableUserEvent)return false;//全局关闭
            var e = event || window.event || arguments.callee.caller.arguments[0];
            var rs=true;
            //var _this=kevlist[kn]._this;
            if(!e || kn==0){
                return;
            }
            
            if(e.keyCode==27){ // 按 Esc 
                if(runKeyEvent(['onkeypress_esc','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kpr_Esc').run(e.keyCode,e)===false){rs=false};
            }else if(e.keyCode==113){ // 按 F2 
                if(runKeyEvent(['onkeypress_f2','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kpr_F2').run(e.keyCode,e)===false){rs=false};
            }else if(e.keyCode==13){ // enter 键
                if(runKeyEvent(['onkeypress_enter','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kpr_Enter').run(e.keyCode,e)===false){rs=false};
            }else if(e.keyCode==8){ // bk 键
                if(runKeyEvent(['onkeypress_backspace','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kpr_Backspace').run(e.keyCode,e)===false){rs=false};
            }else if(e.keyCode==9){ // tab 键
                if(runKeyEvent(['onkeypress_tab','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kpr_Tab').run(e.keyCode,e)===false){rs=false};
            }else if(e.keyCode==17){ // ctrl 键
                if(runKeyEvent(['onkeypress_ctrl','onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
                if(kevlist[kn].event('kpr_Ctrl').run(e.keyCode,e)===false){rs=false};
            }else{
                if(runKeyEvent(['onkeyup_'+e.keyCode,'onkeyup'],e)===false){
                    return false;
                }
            }
            if(kevlist[kn].event('kpr_'+e.keyCode).run(e.keyCode,e)===false){rs=false};
            if(kevlist[kn].event('kpr').run(e.keyCode,e)===false){rs=false};
            return rs;
        };
        
        function keyevent(ev,_this){
            this._this=_this;//(typeof(_this)=='object')?_this:this;
            this._event=ev;//(typeof(ev)=='function')?ev:J4.Event();
            //console.log();
            this._isCan=false;
        }
        keyevent.prototype={
            //_event:(typeof(ev)=='function')?ev:newEvent(),
            __type__:'keyevent',
            event:function(){
                if(!this._this || !this._event){
                    return;
                };
                //console.log(this._event);
                return this._event.apply(this._this,arguments);
            },
            getEvent:function(){
                if(!this._this || !this._event){
                    return;
                };
                //console.log(this._event);
                return this._event.apply(this._this,arguments);
            },
            can_not:function(){
                this._isCan=false;
                kevlist[this.id]=null;
                //console.log(this.id,kn);
                if(this.id==kn){
                    kn--;
                    while(kn){
                        if(!kevlist[kn]){
                            kn--;
                        }else{
                            break;
                        }
                    }
                }
                return this;
            },
            can:function(){
                if(!this._isCan){
                    kn++;
                    this.id=kn;
                    this._isCan=true;
                    kevlist[kn]=this;
                }
                //console.log('event can',kn);
                return this;
            },
            
            //id:kn,
            //_this:(typeof(_this)=='object')?_this:this,
            //defult:defultKeydown,
            getShift:function(){
                return Shiftdown;
            },
            getCtrl:function(){
                return Ctrldown;
            },
            getAlt:function(){
                return Altdown;
            },
            //启用
            /* enable:function(){
                this.enable=true;
            }
            enable:function(){
                this.enable=true;
            } */
            lock100:function(){
                if(J4.data.disableUserEvent){
                    return;
                }
                J4.data.disableUserEvent = true;
                setTimeout(function(){
                    J4.data.disableUserEvent = false;
                },100);
            },
            lock:function(t){
                if(J4.data.disableUserEvent){
                    return;
                }
                J4.data.disableUserEvent = true;
                setTimeout(function(){
                    J4.data.disableUserEvent = false;
                },t);
            },
        }; 
        return function(ev,_this){
            //var ke = new keyevent();
            var fn = function(turn){
                if(turn=='on'){
                    fn._this=this;
                    fn._event=this.event;
                    fn.can();
                }else if(turn=='off'){
                    fn.can_not();
                }    
            };
            Object.setPrototypeOf(fn, keyevent.prototype);
            keyevent.call(fn,ev,_this);    
            return fn;
        }
    })(),
    //让用户选择一个文件 accept是允许的类型，例如图片accept="image/gif, image/jpeg" 
    SelectFile:function(accept,fn,multiple){
        if(typeof(accept)=='function'){
            multiple = fn;
            fn = accept;
            accept = false;
        }else if(typeof(fn)!='function'){
            return false;
        }
        var _this=this;
        var inputObj = document.createElement('input');
        inputObj.addEventListener('change',function(e){
            //console.log(e);
            var value=inputObj.files;
            value.each(function(i,f){
                var name=f.name.split('.');
                name=name[name.length-1];
                f.lastName=name.toLocaleLowerCase();
            });
            value.fullname=inputObj.value;
            if(!multiple){
                value = value[0];
            }
            fn.call(_this,value);
        },false);
        inputObj.type = 'file';
        if(multiple){
            inputObj.multiple = 'multiple';
        }
        if(accept){
            inputObj.accept = accept;
        }
        //inputObj.id = id;
        document.getElementsByTagName('body')[0].appendChild(inputObj);
        inputObj.click();
        setTimeout(function(){
            inputObj.remove();
        },100);
        return inputObj;
    },
    //下载文件__token
    DownFile:function(url,data,filename){
        if(typeof(data)=='string'){
            filename=data;
            data = null;
        }
        if(url && typeof(url)=='object' && (url.__type__=='File'|| url.__type__=='Blob')){
            if(!filename){
                J4.ShowError('下载出错');
                return;
            }
            // IE
            if (window.navigator && window.navigator.msSaveOrOpenBlob) {
                window.navigator.msSaveOrOpenBlob(url, filename);
                return;
            } else {
                var reader = new FileReader();
                reader.readAsDataURL(url);    // 转换为base64，可以直接放入a表情href
                reader.onload = function (e) {
                    var a = document.createElement('a');
                    a.download = filename;//下载文件名
                    a.href = e.target.result;
                    document.body.appendChild(a);// 修复firefox中无法触发click
                    a.click();
                    a.remove();
                }
                    
                //url = window.URL.createObjectURL(url);
                //var link = document.createElement('a');
                //link.style.display = 'none';
                //link.href = url;
                //link.setAttribute('download', filename);
                //document.body.appendChild(link);
                //link.click();
                return;
            }
        }else{ 
            if(typeof(data)=='object'){
                if(url.indexOf('?') > 0){
                    url+='&';
                }else{
                    url+='?';
                }
                data.each(function(i,v){
                    url+=encodeURI(i)+'='+encodeURI(v)+'&';
                },this);
                url = url.Rtrim('&? ');  
            }
            try{ 
                var elemIF = document.createElement("iframe");   
                elemIF.src = url;   
                elemIF.style.display = "none";  
                document.body.appendChild(elemIF);   
            }catch(e){ 
                J4.ShowError('下载出错');
            } 
        }
    },
    //获取图片的缩略图
    ToSmallImg:function(img,w,h){
        var canvas = document.createElement('canvas'); // 创建一个新的canvas
        if(img.width>img.height){
            h = img.height/img.width*w;
        }else{
            w = img.width/img.height*h;
        }
        canvas.width = w;
        canvas.height = h;
        canvas.getContext('2d').drawImage(img,0,0,w,h); 
        var Img = new Image();
        Img.onload = function(){
            this._load = true;
        }
        Img.src = canvas.toDataURL("image/png");
        //console.error(J4.mTime());
        return Img;
    },
    //全屏
    FullScreen:function(el){
        if(!el){
            el=document.getElementsByClassName("J4-topbox")[0];
            if(!el){
                el = document.documentElement;
            }
        }
        var rfs = el.requestFullScreen || el.webkitRequestFullScreen || el.mozRequestFullScreen || el.msRequestFullScreen;
        if (rfs) {
            rfs.call(el);
        }else if (typeof window.ActiveXObject !== "undefined") {
            //for IE，这里其实就是模拟了按下键盘的F11，使浏览器全屏
            var wscript = new ActiveXObject("WScript.Shell");
            if (wscript != null) {
                wscript.SendKeys("{F11}");
            }
        }
    },      
    //退出全屏
    ExitScreen:function(){
        var el = document;
        var cfs = el.cancelFullScreen || el.webkitCancelFullScreen || el.mozCancelFullScreen || el.exitFullScreen;
    
        //typeof cfs != "undefined" && cfs
        if (cfs) {
            cfs.call(el);
        }else if (typeof window.ActiveXObject !== "undefined") {
            //for IE，这里和fullScreen相同，模拟按下F11键退出全屏
            var wscript = new ActiveXObject("WScript.Shell");
            if (wscript != null) {
                wscript.SendKeys("{F11}");
            }
        }
    },
    //充满窗口
    FullWindow:function(el){
        if(_fullWindow){
            J4.ExitFullWindow();
        }
        if(!el){
            el=document.getElementsByClassName("J4-topbox")[0];
            if(!el){
                el = document.documentElement;
            }
        } 
        _fullWindow = el;
        document.getElementsByTagName("body")[0].addClass("fullWindowBody");
        el.addClass("fullWindow");
        var opt = el.fllwindow;
        if(!opt){
            opt = document.createElement("div");
        }
        opt.addClass("fullWindowOpt");
        opt.appendToBefor(el);
        el.fllwindow = opt;
        
        var oid = J4.GetOnlyId();
        J4.event("click").on(oid,function(e){
            if(e.target.hasClass("fullWindow")){
                J4.ExitFullWindow(e.target);
                J4.event("click").off(oid);
            }
        });
        J4.event("onkeydown_esc").on(oid,function(e){
            J4.ExitFullWindow(el); 
            J4.event("onkeydown_esc").off(oid);            
        });
    },
    ExitFullWindow:function(){
        if(!_fullWindow){
            return;
        }
        document.getElementsByTagName("body")[0].removeClass("fullWindowBody");
        _fullWindow.removeClass("fullWindow");
        _fullWindow.fllwindow.remove();
        //_fullWindow.fllwindow = null;
    },
    /*ajax基本方法 这个方法是所有ajax方法的基础*/
    Ajax:(function(){ //function(url,data,returnType,timeout)
        //formdata对象添加数据
        function formdataAppend(formdata,key,val){
            //console.log(key,val,typeof(val));
            var allsize=0;
            if(val && typeof(val)=='object' && (val.__type__=='File'|| val.__type__=='Blob') && val.size>0){
                formdata.append(key, val);
                allsize+=val.size;
            }else if(val && typeof(val)=='object'){
                val.each(function(k,v){
                    //formdata.append(key+'['+k+']', val);
                    allsize+=formdataAppend(formdata,key+'['+k+']',val[k]);
                });
            }else if( val && val.__type__=='FileList'){
                console.error('请先处理FileList');
            }else{
                //val = encodeURIComponent(val);
                if(typeof(key)=='number'){
                    key=key+'';
                }
                if(typeof(val)=='number'){
                    val=val+'';
                }
                if(!val){
                    val='';
                }
                formdata.append(key, val);
                if(typeof(key)=='string'){
                    allsize+=key.length*200;
                }
                if(typeof(val)=='string'){
                    allsize+=val.length*200;
                }
            }
            return allsize;
        }
        //检查是否有文件对象
        function checkFile(data){
            var isfileup=true;
            //var isdata=false;
            data.each(function(key,val){
                //console.log(val.constructor.name);
                if(val && typeof(val)=='object'){
                    if( val.__type__=='File' || val.__type__=='Blob'){
                        isfileup=false;
                    }else{
                        isfileup=checkFile(val);
                    }
                    return isfileup;
                }
            });
            return isfileup;
        }
        //将其中的文件拆成单个的放入根路径
        function resetFile(data,fn){
            data.each(function(key,val){
                if(val && typeof(val)=='object'){
                    if( val.__type__=='FileList'){
                        data[key] = [];
                        val.each(function(i,v){
                            data[key].push(fn(v));
                        });
                    }else if( val.__type__=='File' || val.__type__=='Blob'){
                        data[key] = fn(val);
                    }else{
                        resetFile(val,fn);
                    }
                }
            });
        }
        
        //检查数据是否合法
        function CreateFormData(data,fn){
            if(typeof(data)!='object'){
                return false;
            }
            if(data.__type__=='FormData'){
                return data;
            }
            if(checkFile(data)){
                return data;
            }
            data = J4.CopyObj(data);
            //data['__hasfile__'] = true;//标记含有文件
            var flist ={};
            resetFile(data,function(val){
                var id= J4.GetOnlyId();
                flist[id]=val;
                return id;
            });
            flist.each(function(id,v){
                if(fn)fn(v);
                data[id] = v;
            });
            //console.log(data);
            var allsize=0;       
            var formdata = new FormData();
            data.each(function(key,val){
                allsize+=formdataAppend(formdata,key,val);
            });
            formdata.size=allsize;
            return formdata; 
        }
        
        function runList(_this,fnlist,argu){
            fnlist.each(function(i,v){
                //console.log(v,_this,argu);
                return v.apply(_this._this,argu);
            });
        }
        
        function myAxios(options,_this){
            if(!options.url || typeof(options.url)!='string'){
                console.error('ajax没有指定url值');
                return;
            }
            this.options = {
                url :       encodeURI(options.url),
                urlData :   options.urlData,
                data :      options.data,
                type :      options.type?options.type.toUpperCase():(options.data?'POST':'GET'),
                returnType :options.returnType?options.returnType.toUpperCase():'JSON',
                timeout :   options.timeout?options.timeout:30000,
            }
            this.callBack = {
                start:[],
                loadding:[],
                success:[],
                error:[],
                complete:[],
                fileFilter:[]
            }
            this._this = _this;
        }
        myAxios.prototype = {
            __type__:'Ajax',
            setAttribute:function(name,value){
                this.options[name]=value;
                return this;
            },
            fileFilter:function(fn){
                if(fn==='clear'){
                    this.callBack.fileFilter=[];
                    return this;
                }
                if(typeof(fn)=='function'){
                    this.callBack.fileFilter.push(fn);
                }
                return this; 
            },
            start:function(fn){
                if(fn==='clear'){
                    this.callBack.start=[];
                    return this;
                }
                if(typeof(fn)=='function'){
                    this.callBack.start.push(fn);
                }
                return this; 
            },
            loadding:function(fn){
                if(fn==='clear'){
                    this.callBack.loadding=[];
                    return this;
                }
                if(typeof(fn)=='function'){
                    this.callBack.loadding.push(fn);
                }
                return this;
            },
            success:function(fn){
                if(fn==='clear'){
                    this.callBack.success=[];
                    return this;
                }
                if(typeof(fn)=='function'){
                   this.callBack.success.push(fn); 
                }
                return this;
            },
            error:function(fn){
                if(fn==='clear'){
                    this.callBack.error=[];
                    return this;
                }
                if(typeof(fn)=='function'){
                    this.callBack.error.push(fn);
                }
                return this;
            },
            complete:function(fn){
                if(fn==='clear'){
                    this.callBack.complete=[];
                    return this;
                }
                if(typeof(fn)=='function'){
                    this.callBack.complete.push(fn);
                }
                return this;  
            },
            throwError:function(errorid,errorinfo,xhr){
                runList(this,this.callBack.error,[errorid,errorinfo,xhr,this]);
                //throw errorinfo; 
            },
            run:function(){
                var url = this.options.url;
                if(!url){
                    //this.ShowError();
                    console.error('错误的URL:'+url);
                    runList(this,this.callBack.error,[1,'错误的URL:'+url,null,this]);
                    return null;
                }
                url = url.Rtrim('/ ');               
                if(this.options.urlData){
                    var arr = this.options.urlData;
                    if(arr.__type__=='String'){
                        arr = [arr];
                    }else if(arr.__type__!='Array' && arr.__type__!='BindArray'){
                        console.error('urlData参数必须是字符串或者字符串数组');
                        runList(this,this.callBack.error,[1,'urlData参数必须是字符串或者字符串数组',null,this]);
                        return null;
                    }
                    arr.each(function(i,v){
                        url+='/'+ encodeURI(v.Trim('/ '));
                    });
                }
                if(url.indexOf('?') > 0){
                    url+='&';
                }else{
                    url+='?';
                }
                if(J4.ServerRev){
                    url+="Rev="+J4.ServerRev+'&';
                }
                
                var _this = this;
                var data = this.options.data;
                if(!this.options.type){
                    if(data){
                        this.options.type = 'POST';
                    }else{
                        this.options.type = 'GET';
                    }
                }
                if(this.options.type=='GET'){
                    if(data){
                        data.each(function(i,v){
                            url+=encodeURI(i)+'='+encodeURI(v)+'&';
                        },this);
                    }
                }else if(data&&typeof(data)=='object'){
                    if(this.callBack.fileFilter.length>0){
                        data=CreateFormData(data,function(file){
                            runList(this,this.callBack.fileFilter,[file]);
                        });
                    }else{
                        data=CreateFormData(data);
                    }
                    if(data.__type__=='FormData'){
                        this.dataSize = data.size;
                    }else{
                        data=J4.Json_encode(data);
                        this.dataSize = data.length;
                    }   
                }                    
                
                this.options.data = data;
                url = url.Rtrim('&? ');  
                //开始事件触发
                var xhr=new XMLHttpRequest();//创建连接对象   
                if(J4.DEBUG){
                    xhr.withCredentials = true;
                }
                //超时检查
                var timeout = this.options.timeout;
                var timer=setTimeout(function(){
                    xhr.abort();//请求中止
                    console.error('请求超时',url);
                    //runList(_this,_this.callBack.error,[1,'请求超时!',xhr,_this]);
                    //runList(_this,_this.callBack.complete,['请求超时!',xhr,_this]);
                },timeout);
                //设置header头部分
                xhr.open(this.options.type,url);
                runList(this,this.callBack.start,[xhr,this]);
                if(data && data.__type__!='FormData'){
                    xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
                }
                if(this.options.returnType=='JSON'){
                    xhr.setRequestHeader("Accept", "application/json;charset=utf-8");
                }else if(this.options.returnType=='FILE'){
                    xhr.responseType = 'blob';
                }else if(this.options.returnType){
                    xhr.setRequestHeader("Accept", this.options.returnType);
                }             
                //设置进度处理
                xhr.onprogress = function(e){
                    runList(_this,_this.callBack.loadding,[1,e,xhr,_this]);
                }   
                //这里处理状态事件
                xhr.onreadystatechange = function(){
                    if(xhr.readyState == 4){   
                        clearTimeout(timer);
                        if(xhr.status!=200){
                            console.error("网络请求出错:",url);
                            var rs =J4.Json_decode(xhr.responseText);
                            if(rs){
                                runList(_this,_this.callBack.error,[xhr.status,rs,xhr,_this]);
                                runList(_this,_this.callBack.complete,[rs,xhr,_this]);
                            }else{
                                runList(_this,_this.callBack.error,[xhr.status,xhr.responseText,xhr,_this]);
                                runList(_this,_this.callBack.complete,[xhr.responseText,xhr,_this]);
                            }
                        }else if(_this.options.returnType=='JSON'){
                            var disp = xhr.getResponseHeader('Content-Disposition');
                            if(disp && disp.search('attachment') != -1){
                                console.error('Ajax返回类型不是json!');
                                runList(_this,_this.callBack.error,[6,'Ajax返回类型不是json!',xhr,_this]);
                                runList(_this,_this.callBack.complete,[xhr.responseText,xhr,_this]);  
                            }else if(typeof(xhr.responseText)=='string'){
                                try{
                                    var rs=JSON.parse(xhr.responseText); 
                                }catch(err){
                                    console.error("json简析出错:",err);
                                    runList(_this,_this.callBack.error,[5,'json简析出错!',xhr,_this]);
                                    runList(_this,_this.callBack.complete,[xhr.responseText,xhr,_this]); 
                                    return;
                                }
                                runList(_this,_this.callBack.success,[rs,xhr,_this]);
                                runList(_this,_this.callBack.complete,[rs,xhr,_this]);  
                            }else{
                                console.error('Ajax返回类型不是json!');
                                runList(_this,_this.callBack.error,[6,'Ajax返回类型不是json!',xhr,_this]);
                                runList(_this,_this.callBack.complete,[xhr.responseText,xhr,_this]);  
                            } 
                        }else if(_this.options.returnType=='FILE'){
                            var disp = xhr.getResponseHeader('Content-Disposition');
                            if(disp && disp.search('attachment') != -1){
                                var blob = new Blob([xhr.response], {type:"application/octet-stream"});
                                disp = disp.split('=');
                                blob.filename = disp[1];
                                runList(_this,_this.callBack.success,[blob,xhr,_this]);
                                runList(_this,_this.callBack.complete,[blob,xhr,_this]);  
                            }else{
                                runList(_this,_this.callBack.error,[7,'Ajax返回类型不是File!',xhr,_this]);
                                runList(_this,_this.callBack.complete,[xhr.responseText,xhr,_this]);
                            }
                        }else{
                            runList(_this,_this.callBack.success,[xhr.responseText,xhr,_this]);
                            runList(_this,_this.callBack.complete,[xhr.responseText,xhr,_this]);  
                        }
                    }
                }
                xhr.send(data);
                return xhr;
            },
        }
        
        return function(url,data,returnType,timeout){
            var options;
            if(!url){
                console.error('url不能为空');
                return;
            }
            if(url.__type__ == 'Object'){
                options = url;
            }else if(url.__type__ == 'String'){
                options = {
                    url :       url,
                    data :      data,
                    returnType: returnType,
                    timeout:    timeout
                }
            }else{
                console.error('ajax参数错误');
                return;
            }
            var ajax = new myAxios(options,this);
            setTimeout(function(){
                ajax.run();
            });
            return ajax;
        }
    })(),
    WS:(function(){ //websocket连接，自定义协议实现连接复用
        var wslist = {};
        function getCon(url){
            if(!url){
                url="/";
            }
            var host,path="/";
            if(url.startsWith("ws://")){
                host = "ws://"+ url.substring(5).split("/")[0];
            }else if(url.startsWith("wss://")){
                host = "wss://"+ url.substring(6).split("/")[0];
            }else{
                host = window.location.href;
                if(!url.startsWith("/")){
                    url = "/"+url;
                }
                if(host.startsWith('http://')){
                    host = "ws://"+ window.location.host + url;
                }else if(host.startsWith('https://')){
                    host = "wss://"+ window.location.host + url;
                }else{
                    console.error("无法识别的主机");
                    return null;
                }
            }
            if(wslist[host]){
                return wslist;
            }
            console.log(host);
            var ws = new WebSocket(host);
            //wslist[host] = ws;
            ws.onopen = function(event) {
                console.log("websocket connection open.");
                console.log(event);

            };
    
            ws.onmessage = function(event) {
                console.log("websocket message received.")
                console.log(event.data);
                
            };
    
            ws.onclose = function (event) {
                console.log("websocket connection close.");
                console.log(event.code);
            };
    
            ws.onerror = function(event) {
                console.log("websocket connection error.");
                console.log(event);
            };
            return ws;
        }
        return getCon;
    })(),
    //路由
    CreateRouter:(function(){
        var routerlist = {};    
        function Router(_this,name){
            this._this = _this?_this:this;
            this.name = name;
            this.hash = '';
            this.callBack=[];
            this.isEnable = false;
            this.fatherRouter = null;
            this.auto = false;
        };
        Router.prototype = {
            Add:function(name,fn){
                if(typeof(fn)!='function'){
                    return;
                }
                if(name=='subSet'){
                    this.subSet = fn;
                }else{
                    this.callBack.push({name:name,fn:fn});
                }
            },
            Set:function(hash){//修改hash
                this.Run(hash);  
                if(this.isEnable){
                    setLocationHash();
                }else if(this.fatherRouter && this.fatherRouter.subSet){
                    this.fatherRouter.subSet(this.hash);
                }
            },
            Run:function(hash){
                hash = '/'+hash.Ltrim(' /');
                if(hash==this.hash){
                    return;
                }
                this.hash = hash;
                if(!this._isrun){
                    var _this = this;
                    this._isrun = true;
                    setTimeout(function(){
                        _this._Run();
                        _this._isrun = false;
                    },5);
                }
            },
            _Run:function(){
                var hash = this.hash;
                this.callBack.each(function(i,d){
                    if(hash.startsWith(d.name)){
                        var rs = d.fn.call(this._this,hash.substr(d.name.length));
                        if(rs===false){
                            return false;
                        }else if(typeof(rs)==='string'){//方便规则重写
                            hash = rs;
                            this.hash = hash;
                        }
                    }
                },this);
            },
            Enable:function(){
                if(!this.name){
                    return;
                }
                this.isEnable = true;
                routerlist[this.name]=this;
                if(this.auto){
                    this.Set(this.hash);
                    return;
                }
                var hash = decodeURI(location.hash.slice(1));
                hash = hash.split('#');
                var t = false;
                hash.each(function(i,v){
                    if(!v){
                        return;
                    }
                    var hname = v.split('/')[0];
                    if(this.name==hname){
                        v = v.substr(hname.length);
                        this.Run(v);
                        t=true;
                    }
                },this);
                if(!t){
                    this.Set(this.hash);
                }
            },
            Disable:function(){
                delete(routerlist[this.name]);
                setLocationHash();
            },
            EnableAuto:function(defulthash){
                this.auto = true;  
                if(!this.name){
                    return;
                }
                routerlist[this.name]=this;
                var hash = decodeURI(location.hash.slice(1));
                hash = hash.split('#');
                var t = false;
                hash.each(function(i,v){
                    if(!v){
                        return;
                    }
                    var hname = v.split('/')[0];
                    if(this.name==hname){
                        v = v.substr(hname.length);
                        if(!v){
                            v = defulthash;
                        }
                        this.Run(v);
                        t=true;
                    }
                },this);
                if(!this.hash){
                    this.Set(defulthash);
                }else if(!t){
                    this.Set(this.hash);
                }                
            },
            Reload:function(){
                this.hash='';
                this.Enable();
            },
        };
        var isset = false;
        function setLocationHash(){
            if(isset){
                return;
            }
            isset = true;
            setTimeout(function(){
                var a = '';
                routerlist.each(function(i,v){
                    a+='#'+i+v.hash;
                });
                location.hash = encodeURI(a);
                isset = false;
            },10);
        } 
        window.onhashchange = function(e){
            if(J4.PlugRun){
                if(J4.PlugRun(e)===false){
                    return;
                }
            }
            var hash = decodeURI(location.hash.slice(1));
            //console.log(hash);
            hash = hash.split('#');
            hash.each(function(i,v){
                if(!v){
                    return;
                }
                var name = v.split('/')[0];
                if(!routerlist[name]){
                    console.error('未知路由:'+name);
                    return;
                }
                routerlist[name].Run(v.substr(name.length));
            });
            return false;
        }
        return function(_this,name){
            return new Router(_this,name);
        }
    })(),
    //打印dom元素
    DoPrintDom:function(dom,outerCsslist,title){
        var new_iframe = document.createElement('IFRAME');
        new_iframe.setAttribute('style', 'width:100%;height:100%;position:absolute;left:-2000px;top:-2000px;/*z-index: 9999;*/ ');
        new_iframe.setAttribute('align', 'center');
        document.body.appendChild(new_iframe);
        var doc = new_iframe.contentWindow.document;
        doc.write('<html class="printhtml"><head>');
        doc.write('<meta http-equiv="content-type" content="text/html;charset=utf-8">');
        title = title?title:dom.getAttribute("title");
        if(title){
            doc.write('<title>'+title+'</title>');
        }
        doc.write('<link href="'+J4.ReWiteUrl("/share/css/app-top.css?Rev="+J4.ServerRev)+'" rel="stylesheet" type="text/css">');
        doc.write('<link href="'+J4.ReWiteUrl("/share/css/icon.css?Rev="+J4.ServerRev)+'" rel="stylesheet" type="text/css">');
        if(outerCsslist && typeof(outerCsslist)=='object'){
            outerCsslist.each(function(k,v){
                doc.write(v.outerHTML);
            },this);
        }  
        doc.write('</head><body class="printbody">');    
        doc.write('<div class="printbox">'+dom.innerHTML+'</div>');
        doc.write('</body></html>');
        doc.close();
        new_iframe.contentWindow.window.onload=function(){
            setTimeout(function(){
                new_iframe.contentWindow.focus();
                new_iframe.contentWindow.print();
                if(!J4.DEBUG){
                    new_iframe.remove();
                }
            },100);
        }
    },
    //生成一个完整打印html页
    CreateHtmlDoc:function(dom,outerCsslist,title){
        var doc = '<html class="printhtml">\r\n<head>\r\n<meta http-equiv="content-type" content="text/html;charset=utf-8">';
        title = title?title:dom.getAttribute("title");
        if(title){
            doc+='<title>'+title+'</title>\r\n';
        }
        doc+='<link href="'+J4.ReWiteUrl("/share/css/app-top.css?Rev="+J4.ServerRev)+'" rel="stylesheet" type="text/css">\r\n'+
             '<link href="'+J4.ReWiteUrl("/share/css/icon.css?Rev="+J4.ServerRev)+'" rel="stylesheet" type="text/css">\r\n';
        if(outerCsslist && typeof(outerCsslist)=='object'){
            outerCsslist.each(function(k,v){
                doc+=v.outerHTML;
            },this);
        }  
        doc+='\r\n</head>\r\n<body class="printbody">\r\n'+   
            '<div class="printbox">\r\n'+
            dom.innerHTML+
            '\r\n</div>\r\n</body>\r\n</html>\r\n';
        return doc;
    },
    //其他辅助功能
    //当前登录用户信息获取
    getUserid:function(){
        if(!window.userInfo||!window.userInfo.userlist_id){
            return 0;
        }
        return window.userInfo.userlist_id;
    },
    getUser:function(){
        return J4.CopyObj(window.userInfo);
    },
    testPer:function(per,showError){
        if(!window.userper){
            J4.Msg('用户未登录');
            return false;
        }
        if(window.userper['administrator']){
            return true;
        }
        if(!per){
            per='login';
        }
        if(per=='login'){
            if(window.userInfo&&window.userInfo.userlist_id){
                return true;
            }else{
                J4.Msg('用户未登录');
                return false;
            }
        }
        if(window.userper[per]){
            return true;
        }else{
            if(showError)J4.Msg('用户没有对应功能权限');
            console.error("用户没有"+per+"权限");
            return false;
        }
    },
};
J4.event = J4.Event();
J4.xssConfig = {
    whiteList:{
		style:      ['j4bind'],
		input:      ['j4bind','data','name','utype','j4resize','type','group','value','id','class','style','nameinfo','notspace','readOnly','disabled','placeholder','autofocus','multiple','pname','autocomplete'],
		select:     ['j4bind','data','name','utype','j4resize','type','group','value','id','class','style','nameinfo','readOnly','autofocus'],
		option:     ['j4bind','data','name','utype','j4resize','type','group','value','id','class','style','nameinfo','select','notspace','readOnly','selected','autofocus'],
		textarea:   ['j4bind','data','name','utype','j4resize','type','group','value','id','class','style','nameinfo','notspace','readOnly','rows','cols','autofocus'],
		button:     ['j4bind','data','name','utype','j4resize','type','group','value','id','class','style','nameinfo','autofocus','disabled'],
		header:     ['j4bind','data','name','utype','j4resize','class','type','group','value','id','style'],
		a:          ['j4bind','data','name','utype','j4resize','target', 'href', 'title', 'id','class', 'style',  'group','data-1','data-2','data-3','autofocus'],
		abbr:       ['j4bind','data','name','utype','j4resize','title', 'class', 'style'],
		address:    ['j4bind','data','name','utype','j4resize','class', 'style'],
		//area:     ['j4bind','data','name','utype','j4resize','shape', 'coords', 'href', 'alt'],
		article:    ['j4bind','data','name','utype','j4resize'],
		aside:      ['j4bind','data','name','utype','j4resize'],
		audio:      ['j4bind','data','name','utype','j4resize','autoplay', 'controls', 'loop', 'preload', 'src', 'class', 'style'],
		b:          ['j4bind','data','name','utype','j4resize','class', 'style'],
		bdi:        ['j4bind','data','name','utype','j4resize','dir'],
		bdo:        ['j4bind','data','name','utype','j4resize','dir'],
		big:        ['j4bind','data','name','utype','j4resize',],
		blockquote: ['j4bind','data','name','utype','j4resize','cite', 'class', 'style'],
		br:         ['j4bind','data','name','utype','j4resize',],
		caption:    ['j4bind','data','name','utype','j4resize','class', 'style'],
		center:     ['j4bind','data','name','utype','j4resize',],
		cite:       ['j4bind','data','name','utype','j4resize',],
		code:       ['j4bind','data','name','utype','j4resize','class', 'style'],
		col:        ['j4bind','data','name','utype','j4resize','align', 'valign', 'span', 'width', 'class', 'style'],
		colgroup:   ['j4bind','data','name','utype','j4resize','align', 'valign', 'span', 'width', 'class', 'style'],
		dd:         ['j4bind','data','name','utype','j4resize','class', 'style'],
		del:        ['j4bind','data','name','utype','j4resize','datetime'],
		details:    ['j4bind','data','name','utype','j4resize','open'],
		div:        ['j4bind','data','name','utype','j4resize','class', 'style','id','value','height','width','turnhtml','data-tab'],
		dl:         ['j4bind','data','name','utype','j4resize','class', 'style'],
		dt:         ['j4bind','data','name','utype','j4resize','class', 'style'],
		em:         ['j4bind','data','name','utype','j4resize','class', 'style'],
		font:       ['j4bind','data','name','utype','j4resize','color', 'size', 'face'],
		footer:     ['j4bind','data','name','utype','j4resize',],
        form:       ['j4bind','data','name','utype','j4resize','class', 'enctype', 'style'],
		h1:         ['j4bind','data','name','utype','j4resize','class', 'id', 'style'],
		h2:         ['j4bind','data','name','utype','j4resize','class', 'id', 'style'],
		h3:         ['j4bind','data','name','utype','j4resize','class', 'id', 'style'],
		h4:         ['j4bind','data','name','utype','j4resize','class', 'id', 'style'],
		h5:         ['j4bind','data','name','utype','j4resize','class', 'id', 'style'],
		h6:         ['j4bind','data','name','utype','j4resize','class', 'id', 'style'],
		hr:         ['j4bind','data','name','utype','j4resize','class', 'id','style'],
		i:          ['j4bind','data','name','utype','j4resize','class', 'id', 'style'],
		img:        ['j4bind','data','name','utype','j4resize','src', 'alt', 'title', 'width', 'height', 'id', '_src', 'loadingclass', 'class', 'id', 'data-latex','style'],
		ins:        ['j4bind','data','name','utype','j4resize','datetime'],
		li:         ['j4bind','data','name','utype','j4resize','class', 'id', 'style','data-tab'],
        label:      ['j4bind','data','name','utype','j4resize','class', 'id', 'style','for'],
		mark:       ['j4bind','data','name','utype','j4resize'],
		nav:        ['j4bind','data','name','utype','j4resize','class','id','style'],
		ol:         ['j4bind','data','name','utype','j4resize','class', 'id', 'style'],
		p:          ['j4bind','data','name','utype','j4resize','class', 'id', 'style'],
		pre:        ['j4bind','data','name','utype','j4resize','class', 'id', 'style'],
		s:          ['j4bind','data','name','utype','j4resize'],
		section:    ['j4bind','data','name','utype','j4resize','class', 'id', 'style'],
		small:      ['j4bind','data','name','utype','j4resize'],
		span:       ['j4bind','data','name','utype','j4resize','class', 'style','id' ],
		strong:     ['j4bind','data','name','utype','j4resize','class', 'style','id' ],
		sub:        ['j4bind','data','name','utype','j4resize','class', 'style'],
		sup:        ['j4bind','data','name','utype','j4resize','class', 'style'],
		table:      ['j4bind','data','name','utype','j4resize','width', 'border', 'align', 'valign', 'class', 'style', 'notsroll'],
		tbody:      ['j4bind','data','name','utype','j4resize','align', 'valign', 'class', 'style'],
		td:         ['j4bind','data','name','utype','j4resize','width', 'rowspan', 'colspan', 'align', 'valign', 'class', 'style'],
		tfoot:      ['j4bind','data','name','utype','j4resize','align', 'valign', 'class', 'style'],
		th:         ['j4bind','data','name','utype','j4resize','width', 'rowspan', 'colspan', 'align', 'valign', 'class', 'style'],
		thead:      ['j4bind','data','name','utype','j4resize','align', 'valign', 'class', 'style'],
		tr:         ['j4bind','data','name','utype','j4resize','id','rowspan', 'align', 'valign', 'class', 'style'],
		tt:         ['j4bind','data','name','utype','j4resize'],
		u:          ['j4bind','data','name','utype','j4resize'],
		ul:         ['j4bind','data','name','utype','j4resize','class', 'style'],
		video:      ['j4bind','data','name','utype','j4resize','autoplay', 'controls', 'loop', 'preload', 'src', 'height', 'width', 'class', 'style']
	},
    css:{
        whiteList:{
            "align-content": false,
            "align-items": false,
            "align-self": false,
            "alignment-adjust": false,
            "alignment-baseline": false,
            "all": false,
            "anchor-point": false,
            "animation": false,
            "animation-delay": false,
            "animation-direction": false,
            "animation-duration": false,
            "animation-fill-mode": false,
            "animation-iteration-count": false,
            "animation-name": false,
            "animation-play-state": false,
            "animation-timing-function": false,
            "azimuth": false,
            "backface-visibility": false,
            "background": true,
            "background-attachment": true,
            "background-clip": true,
            "background-color": true,
            "background-image": true,
            "background-origin": true,
            "background-position": true,
            "background-repeat": true,
            "background-size": true,
            "baseline-shift": false,
            "binding": false,
            "bleed": false,
            "bookmark-label": false,
            "bookmark-level": false,
            "bookmark-state": false,
            "border": true,
            "border-bottom": true,
            "border-bottom-color": true,
            "border-bottom-left-radius": true,
            "border-bottom-right-radius": true,
            "border-bottom-style": true,
            "border-bottom-width": true,
            "border-collapse": true,
            "border-color": true,
            "border-image": true,
            "border-image-outset": true,
            "border-image-repeat": true,
            "border-image-slice": true,
            "border-image-source": true,
            "border-image-width": true,
            "border-left": true,
            "border-left-color": true,
            "border-left-style": true,
            "border-left-width": true,
            "border-radius": true,
            "border-right": true,
            "border-right-color": true,
            "border-right-style": true,
            "border-right-width": true,
            "border-spacing": true,
            "border-style": true,
            "border-top": true,
            "border-top-color": true,
            "border-top-left-radius": true,
            "border-top-right-radius": true,
            "border-top-style": true,
            "border-top-width": true,
            "border-width": true,
            "bottom": true,
            "box-decoration-break": true,
            "box-shadow": true,
            "box-sizing": true,
            "box-snap": true,
            "box-suppress": true,
            "break-after": true,
            "break-before": true,
            "break-inside": true,
            "caption-side": false,
            "chains": false,
            "clear": true,
            "clip": false,
            "clip-path": false,
            "clip-rule": false,
            "color": true,
            "color-interpolation-filters": true,
            "column-count": false,
            "column-fill": false,
            "column-gap": false,
            "column-rule": false,
            "column-rule-color": false,
            "column-rule-style": false,
            "column-rule-width": false,
            "column-span": false,
            "column-width": false,
            "columns": false,
            "contain": false,
            "content": false,
            "counter-increment": false,
            "counter-reset": false,
            "counter-set": false,
            "crop": false,
            "cue": false,
            "cue-after": false,
            "cue-before": false,
            "cursor": false,
            "direction": false,
            "display": true,
            "display-inside": true,
            "display-list": true,
            "display-outside": true,
            "dominant-baseline": false,
            "elevation": false,
            "empty-cells": false,
            "filter": false,
            "flex": false,
            "flex-basis": false,
            "flex-direction": false,
            "flex-flow": false,
            "flex-grow": false,
            "flex-shrink": false,
            "flex-wrap": false,
            "float": true,
            "float-offset": false,
            "flood-color": false,
            "flood-opacity": false,
            "flow-from": false,
            "flow-into": false,
            "font": true,
            "font-family": true,
            "font-feature-settings": true,
            "font-kerning": true,
            "font-language-override": true,
            "font-size": true,
            "font-size-adjust": true,
            "font-stretch": true,
            "font-style": true,
            "font-synthesis": true,
            "font-variant": true,
            "font-variant-alternates": true,
            "font-variant-caps": true,
            "font-variant-east-asian": true,
            "font-variant-ligatures": true,
            "font-variant-numeric": true,
            "font-variant-position": true,
            "font-weight": true,
            "grid": false,
            "grid-area": false,
            "grid-auto-columns": false,
            "grid-auto-flow": false,
            "grid-auto-rows": false,
            "grid-column": false,
            "grid-column-end": false,
            "grid-column-start": false,
            "grid-row": false,
            "grid-row-end": false,
            "grid-row-start": false,
            "grid-template": false,
            "grid-template-areas": false,
            "grid-template-columns": false,
            "grid-template-rows": false,
            "hanging-punctuation": false,
            "height": true,
            "hyphens": false,
            "icon": false,
            "image-orientation": false,
            "image-resolution": false,
            "ime-mode": false,
            "initial-letters": false,
            "inline-box-align": false,
            "justify-content": false,
            "justify-items": false,
            "justify-self": false,
            "left": true,
            "letter-spacing": true,
            "lighting-color": true,
            "line-box-contain": false,
            "line-break": false,
            "line-grid": false,
            "line-height": true,
            "line-snap": false,
            "line-stacking": false,
            "line-stacking-ruby": false,
            "line-stacking-shift": false,
            "line-stacking-strategy": false,
            "list-style": true,
            "list-style-image": true,
            "list-style-position": true,
            "list-style-type": true,
            "margin": true,
            "margin-bottom": true,
            "margin-left": true,
            "margin-right": true,
            "margin-top": true,
            "marker-offset": false,
            "marker-side": false,
            "marks": false,
            "mask": false,
            "mask-box": false,
            "mask-box-outset": false,
            "mask-box-repeat": false,
            "mask-box-slice": false,
            "mask-box-source": false,
            "mask-box-width": false,
            "mask-clip": false,
            "mask-image": false,
            "mask-origin": false,
            "mask-position": false,
            "mask-repeat": false,
            "mask-size": false,
            "mask-source-type": false,
            "mask-type": false,
            "max-height": true,
            "max-lines": false,
            "max-width": true,
            "min-height": true,
            "min-width": true,
            "move-to": false,
            "nav-down": false,
            "nav-index": false,
            "nav-left": false,
            "nav-right": false,
            "nav-up": false,
            "object-fit": false,
            "object-position": true,
            "opacity": true,
            "order": false,
            "orphans": false,
            "outline": false,
            "outline-color": false,
            "outline-offset": false,
            "outline-style": false,
            "outline-width": false,
            "overflow": true,
            "overflow-wrap": true,
            "overflow-x": true,
            "overflow-y": true,
            "padding": true,
            "padding-bottom": true,
            "padding-left": true,
            "padding-right": true,
            "padding-top": true,
            "page": false,
            "page-break-after": false,
            "page-break-before": false,
            "page-break-inside": false,
            "page-policy": false,
            "pause": false,
            "pause-after": false,
            "pause-before": false,
            "perspective": false,
            "perspective-origin": false,
            "pitch": false,
            "pitch-range": false,
            "play-during": false,
            "position": true,
            "presentation-level": false,
            "quotes": false,
            "region-fragment": false,
            "resize": false,
            "rest": false,
            "rest-after": false,
            "rest-before": false,
            "richness": false,
            "right": true,
            "rotation": false,
            "rotation-point": false,
            "ruby-align": false,
            "ruby-merge": false,
            "ruby-position": false,
            "shape-image-threshold": false,
            "shape-margin": false,
            "shape-outside": false,
            "size": false,
            "speak": false,
            "speak-as": false,
            "speak-header": false,
            "speak-numeral": false,
            "speak-punctuation": false,
            "speech-rate": false,
            "stress": false,
            "string-set": false,
            "tab-size": false,
            "table-layout": false,
            "text-align": true,
            "text-align-last": true,
            "text-combine-upright": true,
            "text-decoration": true,
            "text-decoration-color": true,
            "text-decoration-line": true,
            "text-decoration-skip": true,
            "text-decoration-style": true,
            "text-emphasis": true,
            "text-emphasis-color": true,
            "text-emphasis-position": true,
            "text-emphasis-style": true,
            "text-height": true,
            "text-indent": true,
            "text-justify": true,
            "text-orientation": true,
            "text-overflow": true,
            "text-shadow": true,
            "text-space-collapse": true,
            "text-transform": true,
            "text-underline-position": true,
            "text-wrap": true,
            "top": true,
            "transform": false,
            "transform-origin": false,
            "transform-style": false,
            "transition": false,
            "transition-delay": false,
            "transition-duration": false,
            "transition-property": false,
            "transition-timing-function": false,
            "unicode-bidi": false,
            "vertical-align": true,
            "visibility": false,
            "voice-balance": false,
            "voice-duration": false,
            "voice-family": false,
            "voice-pitch": false,
            "voice-range": false,
            "voice-rate": false,
            "voice-stress": false,
            "voice-volume": false,
            "volume": false,
            "white-space": true,
            "widows": false,
            "width": true,
            "will-change": false,
            "word-break": true,
            "word-spacing": true,
            "word-wrap": true,
            "wrap-flow": false,
            "wrap-through": false,
            "writing-mode": false,
            "z-index": false,
        }
    }
}
//MD5插件
J4.md5 = (function(){
// https://baike.baidu.com/item/MD5/212708?fr=aladdin
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
http://www.fly63.com/article/detial/2833
*/
    /*
    * Configurable variables. You may need to tweak these to be compatible with
    * the server-side, but the defaults work in most cases.
    */
    var hexcase = 1; /* hex output format. 0 - lowercase; 1 - uppercase        */
    var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance   */
    var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode      */
    
    /*
    * These are the functions you'll usually want to call
    * They take string arguments and return either hex or base-64 encoded strings
    */
    function hex_md5(s) {
        return binl2hex(core_md5(str2binl(s), s.length * chrsz));
    }
    function b64_md5(s) {
        return binl2b64(core_md5(str2binl(s), s.length * chrsz));
    }
    function str_md5(s) {
        return binl2str(core_md5(str2binl(s), s.length * chrsz));
    }
    function hex_hmac_md5(key, data) {
        return binl2hex(core_hmac_md5(key, data));
    }
    function b64_hmac_md5(key, data) {
        return binl2b64(core_hmac_md5(key, data));
    }
    function str_hmac_md5(key, data) {
        return binl2str(core_hmac_md5(key, data));
    }
    
    /*
    * Perform a simple self-test to see if the VM is working
    */
    function md5_vm_test() {
        return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
    }
    
    /*
    * Calculate the MD5 of an array of little-endian words, and a bit length
    */
    function core_md5(x, len) {
        /* append padding */
        x[len >> 5] |= 0x80 << ((len) % 32);
        x[(((len + 64) >>> 9) << 4) + 14] = len;
    
        var a = 1732584193;
        var b = -271733879;
        var c = -1732584194;
        var d = 271733878;
    
        for (var i = 0; i < x.length; i += 16) {
            var olda = a;
            var oldb = b;
            var oldc = c;
            var oldd = d;
    
            a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
            d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
            c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
            b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
            a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
            d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
            c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
            b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
            a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
            d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
            c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
            b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
            a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
            d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
            c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
            b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
    
            a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
            d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
            c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
            b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
            a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
            d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
            c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
            b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
            a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
            d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
            c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
            b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
            a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
            d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
            c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
            b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
    
            a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
            d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
            c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
            b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
            a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
            d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
            c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
            b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
            a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
            d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
            c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
            b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
            a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
            d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
            c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
            b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
    
            a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
            d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
            c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
            b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
            a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
            d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
            c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
            b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
            a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
            d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
            c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
            b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
            a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
            d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
            c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
            b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
    
            a = safe_add(a, olda);
            b = safe_add(b, oldb);
            c = safe_add(c, oldc);
            d = safe_add(d, oldd);
        }
        return Array(a, b, c, d);
    
    }
    
    
    
    function safe_add(x, y) {
        var lsw = (x & 0xFFFF) + (y & 0xFFFF);
        var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
        return (msw << 16) | (lsw & 0xFFFF);
    }
    function md5_cmn(q, a, b, x, s, t) {
        var num = safe_add(safe_add(a, q), safe_add(x, t));
        return safe_add((num << s) | (num >>> (32 - s)), b);
    }
    function md5_ff(a, b, c, d, x, s, t) {
        return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
    }
    function md5_gg(a, b, c, d, x, s, t) {
        return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
    }
    function md5_hh(a, b, c, d, x, s, t) {
        return md5_cmn(b ^ c ^ d, a, b, x, s, t);
    }
    function md5_ii(a, b, c, d, x, s, t) {
        return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
    }
    
    /*
    * Calculate the HMAC-MD5, of a key and some data
    */
    function core_hmac_md5(key, data) {
        var bkey = str2binl(key);
        if (bkey.length > 16)
            bkey = core_md5(bkey, key.length * chrsz);
    
        var ipad = Array(16),
        opad = Array(16);
        for (var i = 0; i < 16; i++) {
            ipad[i] = bkey[i] ^ 0x36363636;
            opad[i] = bkey[i] ^ 0x5C5C5C5C;
        }
    
        var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
        return core_md5(opad.concat(hash), 512 + 128);
    }
                   
    /*
    * Convert a string to an array of little-endian words
    * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
    */
    function str2binl(str) {
        var bin = Array();
        var mask = (1 << chrsz) - 1;
        for (var i = 0; i < str.length * chrsz; i += chrsz)
            bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (i % 32);
        return bin;
    }
    
    /*
    * Convert an array of little-endian words to a string
    */
    function binl2str(bin) {
        var str = "";
        var mask = (1 << chrsz) - 1;
        for (var i = 0; i < bin.length * 32; i += chrsz)
            str += String.fromCharCode((bin[i >> 5] >>> (i % 32)) & mask);
        return str;
    }
    
    /*
    * Convert an array of little-endian words to a hex string.
    */
    function binl2hex(binarray) {
        var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
        var str = "";
        for (var i = 0; i < binarray.length * 4; i++) {
            str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) +
            hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF);
        }
        return str;
    }
    
    /*
    * Convert an array of little-endian words to a base-64 string
    */
    function binl2b64(binarray) {
        var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var str = "";
        for (var i = 0; i < binarray.length * 4; i += 3) {
            var triplet = (((binarray[i >> 2] >> 8 * (i % 4)) & 0xFF) << 16)
            | (((binarray[i + 1 >> 2] >> 8 * ((i + 1) % 4)) & 0xFF) << 8)
            | ((binarray[i + 2 >> 2] >> 8 * ((i + 2) % 4)) & 0xFF);
            for (var j = 0; j < 4; j++) {
                if (i * 8 + j * 6 > binarray.length * 32)
                    str += b64pad;
                else
                    str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F);
            }
        }
        return str;
    }
           
    File.prototype.md5=function(callback){
        var reader = new FileReader();
        reader.onload=function(){
            callback(hex_md5(reader.result));
        }
        reader.readAsBinaryString(this);
    }
    return function(str,callBack){
        if(typeof(str)=='string'){
            return hex_md5(str);
        }
        if(str && str.__type__=='File'){
            var reader = new FileReader();
            reader.onload=function(){
                callback(hex_md5(reader.result));
            }
            reader.readAsBinaryString(str);
        }
        return null;
    }
})();        
J4.path = (function(){
    var url = window.location.pathname;
    var u = url.split('/');
    return url.substring(0,url.length-u[u.length-1].length);
})()

var loaddingModule;
var _jsList ={};
var J4Module = {
    apiPath:J4.path,
    srcPath:J4.path.Trim("/").split("/")[0]+"/",//模块会被覆盖
    set loaddingModule(v){
        loaddingModule =v;
    },
    get loaddingModule(){
        return loaddingModule;
    },
    get jsList(){
        return _jsList;
    },
    Router:function(hash){
        if(!this.router){
            console.error('模块未定义路由',this);
            return;
        }
        this.router.Set(hash);
    },
    /*设置配置数据
    如果没有设置过，则使用默认的配置
    */
    /*config:J4.CFG,//确保不会读取错误
    Config:function(_CFG){//方法需要优化
        if(!this.config){
            this.config=J4.CopyObj(CFG);
        }
        if(typeof(_CFG)!='object'){
            return;
        }   
        _CFG.each(function(k,v){
            if(k=='XSS_whiteList'){
                this.xssConfig = v;
            }else if(k=='add_XSS_targer'){
                if(!this.xssConfig){
                    this.xssConfig = Tool.CopyObj(xssConfig);
                }
                v.each(function(tname,attrlist){
                    this.xssConfig.whiteList[tname]=attrlist;
                },this);
            }else if(k=='add_XSS_css'){
                if(!this.xssConfig){
                    this.xssConfig = Tool.CopyObj(xssConfig);
                }
                v.each(function(tname,attrlist){
                    this.xssConfig.css.whiteList[tname]=attrlist;
                },this);
            }else{
                this.config[k]=v;
            }
        },this);
    },
    */
    //检查文件类型是否合法
    CheckFile:function(files,typelist,fn,_this){
        if(!typelist){
            typelist=this.config.upfiletype?this.config.upfiletype:CFG.upfiletype;
        }
        if(!_this){
            _this=this;
        }
        if(typelist && typelist.__type__=='String'){
            typelist = typelist.split('/,|;/g');
        }
        var error = false;
        files.each(function(i,v){
            var name=v.name.split('.');
            name=name[name.length-1].toLocaleLowerCase();
            if(v.size==0){
                var istrue=true;
                typelist.each(function(i,t){
                    if(!t){
                        return;
                    }
                    typelist[i] = t.Trim('.').toLocaleLowerCase();
                    if(v == typelist[i]){
                        istrue = false;
                        return false;
                    }
                });
                if(istrue){
                    if(typeof(fn)=='function'){
                        fn.call(_this,v);
                    }
                    error = v;
                    return false;
                }              
            }
        },this);
        return error;
    },   
    /*ajax基本方法 这个方法是所有ajax方法的基础*/
    Ajax:J4.Ajax,//function(url,data,returnType,timeout)
    /*url默认重写规则,
    可以通过重新定义下面方法达到特定类用特定的url规则
        ReWiteDownUrl 下载链接
        ReWiteCssUrl  css地址
        ReWiteJsUrl   Js类地址
        ReWiteOutJsUrl 三方js
        ReWiteSrcUrl 其他资源文件
        ReWiteAppUrl api请求
        ReWiteTplUrl 模板文件
        
    */
    ReWiteUrl:function(url,type){        
        if(!url){
            return url;
        }
        url = url.Trim();
        if(url.startsWith('http://') || url.startsWith('https://')){
            return url;
        } 
        
        if(type=='api'){
            if(!url.startsWith('/')&&this.apiPath){
                url = this.apiPath+url;
            }
            if(url.startsWith('http://') || url.startsWith('https://')){
                return url;
            }
            url = J4.apiBasePath+url.Trim('/');
        }else{           
            if(!url.startsWith('/')&&this.srcPath){
                url = this.srcPath+url;
            }
            if(url.startsWith('http://') || url.startsWith('https://')){
                return url;
            }
            if(J4.srcBasePath && !url.startsWith(J4.srcBasePath)){
                url = J4.srcBasePath+url.Trim('/');
            }
        }
        if(!url.startsWith('http://') && !url.startsWith('https://')){
            url = baseUrl+url;
        }
        return url;
    },
    //加载一个js文件并执行(不包括依赖加载)
    GetScript:(function(){
        function getMod(url,rs,tpl,css){
            if(rs){
                var scr=document.createElement('script');
                scr.innerHTML='"use strict";\r\n'+rs;
                document.getElementsByTagName('head')[0].appendChild(scr);
                scr.remove();
            }
            var jsList = this.jsList[url];
            var u = url.split('/');
            var srcPath = url.substring(0,url.length-u[u.length-1].length);
            if(this.loaddingModule){
                this.jsList[url] = this.loaddingModule;
                var obj = this.jsList[url];
                if(obj.__type__=='Module' || obj.__type__=='J4Dom'){
                    obj.srcPath = srcPath;
                    if(obj.cfgObj && obj.__type__=='J4Dom'){
                        obj.cfgObj.srcPath = obj.srcPath;
                        obj = obj.cfgObj;
                    }
                    obj.style = css;
                    if(tpl){
                        obj.subDom = {};
                        tpl.each(function(i,dom){
                            var name = dom.getAttribute('subDom');
                            if(!name){
                                if(obj.tpl){
                                    console.error('一个文件只能有一个主div');
                                }
                                obj.dom = dom;
                            }else{
                                obj.subDom[name] = dom;
                            }
                        },this);
                    }
                }else{
                    this.jsList[url] = {url:url,type:'obj',obj:obj,tpl:tpl,style:css,srcPath:srcPath};
                }
            }else{
                //console.log('未发现模块定义代码:'+url);
                this.jsList[url] = {url:url,type:'other',tpl:tpl,style:css,srcPath:srcPath};
            }
            this.loaddingModule = null; 
            //console.log(url,this.jsList);           
            this.setTimeout(function(){    
                jsList.each(function(i,v){
                    v.call(this,this.jsList[url]);
                },this);  
            });
            return this.jsList[url];
        }
        function ReWiteUrl(srcPath,url){
            if(!url.startsWith('/')&&srcPath){
                url = srcPath+url;
                if(!url.startsWith('http://') && !url.startsWith('https://')){
                    url = baseUrl+url;
                }
            }else{
                url = this.ReWiteUrl(url,'mod')
            }
            if(J4.ServerRev){
                if(url.indexOf("?") >= 0){
                    url+='&Rev='+J4.ServerRev;
                }else{
                    url+='?Rev='+J4.ServerRev;
                }
            }
            return url;
        }
        return function(url,fn){
            //console.log(url,this.srcPath)
            url = this.ReWiteUrl(url,'mod');
            var path = url.split('/');
            path = url.substring(0,url.length-path[path.length-1].length);
            
            if(!this.jsList[url]){
                this.jsList[url]=[];
                if(typeof(fn)=='function'){
                    this.jsList[url].push(fn);
                }
            }else if(this.jsList[url] && typeof(this.jsList[url])=='object' && this.jsList[url].__type__=='Array'){
                this.jsList[url].push(fn);
                return;
            }else{
                if(typeof(fn)=='function'){
                    this.setTimeout(function(){   
                        fn.call(this,this.jsList[url]);
                    });
                }
                return;
            }
            return this.Ajax(url,null,'application/mod;charset=utf-8').success(function(rs){    
                rs = rs.Ltrim();
                this.loaddingModule = null; 
                if(rs.startsWith('<')){//带模板的html
                    var dom=document.createElement('div');
                    dom.innerHTML = rs;
                    //这里简析模板
                    //这里插入body使得js部分被执行
                    var css='';// = dom.getElementsByTagName('style');
                    var link = [];
                    var tpl=[];// = dom.getElementsByTagName('template');
                    var src=[];// = dom.getElementsByTagName('script')[0];
                    var srcText = '';
                    var murl=false;// = src.getAttribute('src');
                    
                    dom.children.each(function(i,v){
                        var type = v.nodeName;
                        switch(type){
                            case 'LINK':
                                v.setAttribute('href',ReWiteUrl.call(this,path,v.getAttribute('href')));
                                src.push(v);
                                link.push(v);
                                break;
                            case 'STYLE':
                                css+=v.innerHTML;
                                break;
                            case 'DIV':
                            case 'TEMPLATE':
                                tpl.push(v);
                                break;
                            case 'SCRIPT':
                                if(v.getAttribute('type')=='J4mod'){
                                    if(murl){
                                        console.error('一个文件只能写一个模块');
                                    }
                                    murl = v.getAttribute('src');
                                    if(J4.ServerRev){
                                        if(murl.indexOf("?") >= 0){
                                            murl+='&Rev='+J4.ServerRev;
                                        }else{
                                            murl+='?Rev='+J4.ServerRev;
                                        }
                                    }
                                }else{
                                    var u = v.getAttribute('src');
                                    if(u){
                                        v.setAttribute('src',ReWiteUrl.call(this,path,u));
                                        src.push(v);
                                    }else{
                                        srcText+=';'+v.innerHTML;
                                    }
                                }
                                break;
                        }
                    },this);
                    var head = document.getElementsByTagName('HEAD')[0];
                    if(css){
                        var style = document.createElement('style');
                        style.innerHTML = css;
                        head.appendChild(style);
                        link.push(style);
                    }
                    src.each(function(i,v){
                        head.appendChild(v);
                    });
                    if(murl){
                        if(srcText){
                            var script=document.createElement('script');
                            script.innerHTML='"use strict";\r\n'+srcText;
                            head.appendChild(script);
                            script.remove();
                        }
                        var u = url.split('/');
                        murl = url.substring(0,u.length-u.length)+'js/'+murl;
                        this.Ajax(murl,null,'application/mod;charset=utf-8').success(function(rs){
                            this.loaddingModule = null;     
                            getMod.call(this,url,rs,tpl,link); 
                        }).error(function(errid,errinfo){
                            this.setTimeout(function(){
                                J4.Msg('模块加载错误','url:'+url); 
                            },200);
                            getMod.call(this,url,null,null,null); 
                        });
                    }else{
                        getMod.call(this,url,srcText,tpl,link); 
                    }
                }else{
                    getMod.call(this,url,rs,null,null); 
                }
            }).error(function(errid,errinfo){
                this.setTimeout(function(){
                    J4.Msg('模块加载错误','url:'+url); 
                },200);
                getMod.call(this,url,null,null,null); 
            });
        }
	})(),
    //相关js文件加载完成后执行回调
    Require:function(mlist,callBack){
        if(typeof(callBack)=='string'){
            var cn = callBack;
            callBack = function(mod){
                if(mlist && (mlist.__type__=='Array' || typeof(mlist)=='string')){
                    arguments.each(function(i,v){
                        if(!v[cn]||typeof(v[cn])!='function'){
                            console.error('方法不存在：'+cn,v);
                            return;
                        }
                        v[cn]();
                    });
                }else{
                    mod.each(function(i,v){
                        if(!v[cn]||typeof(v[cn])!='function'){
                            console.error('方法不存在：'+cn,v);
                            return;
                        }
                        v[cn]();
                    });
                }
            }           
        }
        if(!mlist){
            if(typeof(callBack)=='function'){
                callBack.call(this,{});
            }
            return;
        }
        if(typeof(mlist)=='string'){
            mlist=mlist.split(/,|;/g);
        }
        if(typeof(mlist)!='object'){
            console.error('依赖列表无法识别:');
            console.error(typeof(mlist));
            console.error(mlist.constructor.name);
            return;
        }
        if(mlist.isEmpty()){
            if(typeof(callBack)=='function'){
                callBack.call(this,{});
            }
            return;
        }
        var len=0;//mlist.length;
        var _this=this;
        var outObj = J4.CopyObj(mlist);
        mlist.each(function(k,v){
            len++;
            v=v.Trim();
            this.GetScript(v,function(obj){               
                outObj[k] = obj;
                if(obj.___onloade){
                    len--;
                    if(len==0){
                        if(typeof(callBack)=='function'){
                            if(outObj.__type__=='Array'){
                                callBack.apply(_this,outObj);
                            }else{
                                callBack.call(_this,outObj);
                            }    
                        }
                    }
                    return;
                }
                obj.___onloade = true;
                var rq = false;               
                if(obj && obj.__type__=='J4Dom' && obj.cfgObj.require){
                    rq =  obj.cfgObj.require;
                }else if(obj && obj.__type__=='Module' && obj.require){
                    rq = obj.require;
                }
                if(rq){
                    obj.Require(rq,function(objlist){
                        if(obj._onload){
                            obj._onload(objlist);
                        }
                        len--;
                        if(len==0){
                            if(typeof(callBack)=='function'){
                                if(outObj.__type__=='Array'){
                                    callBack.apply(_this,outObj);
                                }else{
                                    callBack.call(_this,outObj);
                                }
                            }
                        }
                    });
                }else{
                    if(obj && obj._onload){
                        obj._onload();
                    }                    
                    len--;
                    if(len==0){
                        if(typeof(callBack)=='function'){
                            if(outObj.__type__=='Array'){
                                callBack.apply(_this,outObj);
                            }else{
                                callBack.call(_this,outObj);
                            }    
                        }
                    }
                }
            });
        },this);  
        if(len==0){
            if(typeof(callBack)=='function'){
                if(outObj.__type__=='Array'){
                    callBack.apply(_this,outObj);
                }else{
                    callBack.call(_this,outObj);
                }    
            }
        }        
    },
        
    //ajax请求服务器上的json数据
    CreateJsonAjax:(function(){
        function JsonCheck(rs,xhr,ajax){
            var type =  ajax.options.jsonType;
            if(rs['debug']){
                if(console.serverlog)console.serverlog(rs['debug']);//输出调试信息
                delete(rs['debug']);
            }
            if(rs['status']===undefined){
                return;
            }else if(rs['status']===null || (rs['status']!='0' && rs['status']!=0)){//服务器业务错误
                if(rs['str']){
                    console.error(rs['str']);
                    ajax.throwError(rs['status'],rs,xhr);
                }else{
                    console.error("返回数据格式不正确:",rs);
                    ajax.throwError(rs['status'],'返回数据格式不正确',xhr);
                }
                return false;
            }else if(type && rs['objType']!=type){ //类型不匹配
                console.error("返回数据类型不匹配,请求类型为"+type+
                    (rs['objType']?(',返回类型为'+rs['objType']):''));   
                ajax.throwError(rs['status'],'返回数据类型不匹配',xhr); 
                return false;
            }
        }       
        return function(url,data,jsonType,notshowloadding){
            url = this.ReWiteUrl(url,'api');
            if(!notshowloadding)this.startLoadding();
            var ajax = this.Ajax(url,data,'JSON')
                       .setAttribute('jsonType',jsonType)
                       //.start(this.startLoadding)
                       .success(JsonCheck)
                       .error(this.OnAjaxError);
            if(!notshowloadding)ajax.complete(this.stopLoadding);
            return ajax;
        }                       
    })(),
    GetJson:function(url,data,notShowLoadding){
        if(data && data.__type__=='Boolean'){
            notShowLoadding = data;
            data = null;
        }
        return this.CreateJsonAjax(url,data,null,notShowLoadding).setAttribute('type','GET');        
    },
    PostJson:function(url,data,notShowLoadding){
        return this.CreateJsonAjax(url,data,null,notShowLoadding).setAttribute('type','POST');    
    },
    OnAjaxError:function(errid,errinfo){
        if(errid==1005){
            this.Require('/Users/login.mod',function(mod){
                mod.create().show();
            });
            return;
        }
        if(errinfo['debug']){
            if(console.serverlog)console.serverlog(errinfo['debug']);//输出调试信息
            errinfo['debug']=undefined;
        }
        J4.Msg('通讯错误',errinfo.str);   
        
    },
    //保留兼容以前代码
    AjaxJson:function(url,data,jsonType,successfn,loaddingFn,timeout){
        if(typeof(data)=='function'){
            successfn = data;
            data = null;
            jsonType = 'GET'
        }else if(typeof(jsonType)=='function'){
            successfn = jsonType;
            jsonType = false;
        }
        return this.CreateJsonAjax(url,data,jsonType)
                   .setAttribute('timeout',timeout?timeout:30000)
                   .success(successfn)
                   .loadding(loaddingFn);
    },
    //图片对象请求 
    GetImg:function(src,fn,errfn){
        if(!src){
            return;    
        }
        if(typeof(src)=='object' && src.__type__ === 'Image'){
            if(typeof(fn)=='function'){
                fn.call(this,src);
            }
            return src;
        }
        var _this=this;
        this.startLoadding();             
        var Img = new Image();//为了避免每次读取耗时太大，这里可以缓存到内存不释放
        Img.onload = function(){
            this._load = true;
            _this.stopLoadding();  
            if(typeof(fn)=='function'){
                fn.call(_this,this);
            }
        }
        
        Img.onerror = function(e){
            console.error(e);
            if(typeof(errfn)=='function'){
                errfn.call(this,e);
            }
            _this.stopLoadding();  
        }
        if(typeof(src)=='object' && (src.__type__ ==='File'||src.__type__ ==='Blob')){                  
            this.startLoadding()
            var reader = new FileReader();  
            reader.onload=function(){
                Img.src = this.result;
                _this.stopLoadding(); 
            }
            reader.readAsDataURL(src);
        }else{
            Img.src = this.ReWiteUrl(src,'api');
        }
        return Img;
    },
    //下载文件__token
    DownFile:function(url,data,filename){
        if( url && typeof(url)=='string'){
            url=this.ReWiteUrl(url,'api');     
        }
        J4.DownFile(url,data,filename);
    },

    //用户选择一个文件(淘汰的方法，兼容以前的代码)    
    GetFile:function(multiple,fn,accept){
        console.error('J4Module.GetFile已经淘汰，请使用SelectFile方法替换');
        if(typeof(multiple)=='function'){
            accept=fn;
            fn=multiple;
            multiple = false;
        }else if(typeof(fn)!='function'){
            return false;
        }
        return this.SelectFile(accept,fn,multiple);
    },   
    //让用户选择一个文件 accept是允许的类型，例如图片accept="image/gif, image/jpeg" 
    SelectFile:J4.SelectFile,
    //快速定义一些快捷键(对hotkeyEvent的包装)
    Funkey:function(keylist,fn){
        var funkey;// = Tool.HotkeyEvent(Tool.Event(),this);       
        if(typeof(keylist)=='function' && keylist.__type__=='event'){
            funkey = J4.HotkeyEvent(keylist,this);
        }else if(typeof(keylist)=='string' && keylist && typeof(fn)=='function'){
            funkey = J4.HotkeyEvent(J4.Event(),this);
            funkey.event(keylist).on(fn,this);
            //console.log(funkey._event.id);
        }else{
            funkey = J4.HotkeyEvent(J4.Event(),this);
        }
        //funkey.can();
        return funkey;
    },
    
    FilterXss:function(html){
        return J4.FilterXss(html);
    },

    //markdown文档转为html，需要先加载依赖后调用，否则将调用失败
    MarkdownToHtml:function(mtext){
        if(!J4.MarkdowObj){
            console.error('请将markdown.js加入到依赖列表中');
        }
        return J4.MarkdowObj.makeHtml(mtext);
    },
    
    //异步执行
    setTimeout:function(fn,t){
        if(typeof(fn)!=='function'){
            return null;
        }
        var _this=this;
        if(t===undefined){
            return setTimeout(function(){fn.apply(_this,arguments)});
        }else{
            return setTimeout(function(){fn.apply(_this,arguments)},t);
        }
    },
    
    //确保加载后执行
    loadedRun:function(fn){
        if(typeof(fn)!='function'){
            return;
        }
        if(this.isLoaded){
            fn.call(this)
        }else{
            this.event('loaded').once(function(){
                fn.call(this)
            });
        }
    },
    Extend:function(obj){    
        if(typeof(obj)=='object'){
            var prop = Object.getPrototypeOf(this);
            Object.setPrototypeOf(obj,prop);
            Object.setPrototypeOf(this,obj);
        }
    },

};
//Object.setPrototypeOf(J4Module,J4);  
J4.Module = J4Module;
J4.Require = function(mlist,callBack){
    return J4Module.Require(mlist,callBack);
}
J4.ReWiteUrl = function(a,b){
    return J4Module.ReWiteUrl(a,b);
}
//扩展J4对象
J4.Extend = function(requireList,fn,obj){
    if(arguments.length>2){
        J4Module.Require(requireList);
    }else if(requireList && requireList.__type__=='String'){
        J4Module.Require(requireList);
    }else{
        obj = fn;
        fn = requireList;
    }
    if(typeof(obj)=='function'){
       var a=obj;
       obj=fn;
       fn=a;
    }        
    if(typeof(obj)=='object'){
        var j4obj = Object.getPrototypeOf(J4);
        Object.setPrototypeOf(obj,j4obj);
        Object.setPrototypeOf(J4,obj);
    }
    if(typeof(fn)=='function'){
        fn.call(J4);
        if(obj && typeof(obj.Init)=='function'){
            obj.Init.call(J4);
        }
    }
}
//带getter setter的类,用来将数据也特定操作绑定
function DataSet(data){
    this._bindData=this.__NewIndexArray("");
    this._setcount=0;
    this.callList = {};
    this.oid =J4.GetOnlyId();
    if(data){
        this.data = data;
    }
}
DataSet.prototype={
    __type__:'DataSet',
    change:function(oid,fn,_this){
        if(typeof(oid)=='function'){
            _this = fn;
            fn=oid;
            oid = J4.GetOnlyId();
        }
        if(typeof(fn)!='function'){
            return;
        }
        if(!_this){
            _this = this;
        }    
        this.callList[oid] = [fn,_this];
        fn.call(_this,'/',this.data,this.data);
    },
    removeCallBack:function(fn){
        if(typeof(fn)=='function'){
            delete(this.callList[fn.oid]);
        }else{
            delete(this.callList[fn]);
        }
    },
    runCallback:function(name,value,oldValue){
        this.callList.each(function(i,v){
            v[0].call(v[1],name,value,oldValue);
        },this);
    },
    __Unlock:function(name,o,lastO){
        if(this._setcount>0){
            this._setcount--;
        }
        if(this._setcount==0){
            this.runCallback('/'+name,o,lastO); 
        }
    },
    __Lock:function(){
        this._setcount++;
    },
    TestLock:function(){
        if(this._setcount==0){
            return true;
        }else{
            return false;
        }
    },
    __Bind:function(name,obj,pro,value){
        //console.error('bind:',name,obj,pro);
        if(pro.startsWith && pro.startsWith('__')){
            return;
        }
        name = name?(name.Trim(' /') + '/' + pro):pro;
        if(pro in obj){
            var a=Object.getOwnPropertyDescriptor(obj,pro);
            if(a&&a.set){
                if(value!==undefined){
                    obj[pro]=value;
                }
                return false;
            }
        }else{
            obj[pro]=null;//J4.NewBindObj();
        } 
        if(value===undefined){
            value=obj[pro];
        }
        var _this=this;
        var o = undefined;//obj[pro];
        //console.log('bind',name,pro);
        Object.defineProperty(obj,pro,{
            //configurable: true,
            enumerable:true,
            set:function(val){ 
                if(o===val){
                    return;
                }
                if(val=="prjInvoiceGroup"){
                    console.log(o,val);
                }
                var lastO=o; 
                if(val === null || val === undefined ){
                    _this.__Lock();
                    o = null;
                    _this.__Unlock(name,o,lastO);
                }else if(typeof(val)=='object'){
                    _this.__Lock();
                    //为了避免不必要的问题，这里统一重置object和Array类型
                    if(Array.isArray(val) || val.__type__=="BindArray"){
                        o = _this.__NewBindArray(name);
                    }else if(val.__type__=="indexArray"){
                        o = _this.__NewIndexArray(name);
                    }else if(val.__type__ === 'Image'){
                         o = val;
                        _this.__Unlock(name,o,lastO);
                        return;
                    }else if( FileList.prototype.isPrototypeOf(val) || File.prototype.isPrototypeOf(val) || Blob.prototype.isPrototypeOf(val)){
                        o = val;
                        _this.__Unlock(name,o,lastO);
                        return;
                    }else{
                        o = _this.__NewIndexArray(name);
                    }    
                    var n = 0;
                    val.each(function(i,v){
                        if(typeof(v)=='function'){
                            return;
                        }
                        if(i.startsWith && i.startsWith('__')){
                            return;
                        }
                        if(o[i]!==undefined){
                            console.error('绑定系统属性名称将造成系统属性方法被请修改,将造成意想不到的错误:',name,i,o[i],val[i]);
                        }
                        _this.__Bind(name,o,i,v); 
                        n++;
                    },this);
                    if(o.__setLength){
                        o.__setLength(n);
                    }
                    _this.__Unlock(name,o,lastO);
                }else{
                    _this.__Lock();
                    o=val;
                    _this.__Unlock(name,o,lastO);
                }
            },
            get:function(){
                return o;
            }
        });
        obj[pro]=value;
    },
    Set:function(sname,value){
        if(typeof(sname)=='object'){
            value=sname;
            if(typeof(value)!='object'){
                console.error('Set数据错误');
                return;
            }
            this.__Lock();  
            value.each(function(i,v){
                if(typeof(v)=='function'){
                    return;
                }
                this.__Bind(false,this._bindData,i,v);   
            },this);
            this.__Unlock("/",value,this._bindData);
            return value;
        }else if(typeof(sname)!='string'){
            return;
        }
        //console.log(name,value);
        var name=sname.Trim(' /').split('/');
        var len=name.length;
        var now=this._bindData;
        if(len==0){
            return;
        }            
        this.__Lock();   
        var oname ="";
        var obj = [['/',this._bindData,null]];
        for(var i=0,len=name.length-1;i<len;i++){
            if(name[i]=='length'){
                return null;
            }
            if(name[i]==='counter' || name[i]==='__id' || name[i]=='__father_id' || name[i]=='__del'){
                this._setcount--;
                console.log('错误的参数:',sname+='/'+v);
                return null;
            }
            if(name[i]=='__father'||name[i]=='..'){
                if(i<1){
                    this._setcount--;
                    return undefined;
                }else{
                    obj[i+1]=obj[obj[i][2]];
                    continue;
                }
            }else if(name[i]=='__value'){
                 obj[i+1]=obj[i];
            }
            if(obj[i][1]===null || typeof(obj[i][1])!='object'){
                obj[obj[i][2]][1][obj[i][0]] = {};
                obj[i][1]=obj[obj[i][2]][1][obj[i][0]];
            }
            this.__Bind(oname,obj[i][1],name[i]);
            oname = oname + "/" + name[i];
            obj[i+1]=[name[i],obj[i][1][name[i]],i];
        }
        var i = name.length-1;
        var v = name[i];  
        if(v=='length'){
            return null;
        }
        if(v=='counter' || v=='__id' || v=='__father_id'){
            console.log('错误的参数:',oname+='/'+v);
            this._setcount--;
            return;
        } 
        var lastO;
        if(v==='__value' || v==='__father' || v==='..'){
            lastO =  obj[i][1];
            obj[obj[i][2]][1][obj[i][0]]=value;
        }else if(v==='__del'){
            if(typeof(value)=='string' || typeof(value)=='number'){
                //console.log('del',oname,value);
                lastO = obj[i][1][value];
                obj[i][1].del(value);
                oname=oname?(oname+'/'+value):value;
                value = undefined;
            }else{
                console.log('错误的参数:',oname+='/'+v);
                this._setcount--;
                return;
            }
        }else{   
            if(obj[i][1]===null || typeof(obj[i][1])!='object'){
                obj[obj[i][2]][1][obj[i][0]] = {};
                obj[i][1]=obj[obj[i][2]][1][obj[i][0]];
            }
            lastO = obj[i][1][v];
            this.__Bind(oname,obj[i][1],v,value);
            oname=oname?(oname+'/'+v):v;         
        }
        this.__Unlock(oname.Trim('/'),value,lastO);
        return value;        
    },
    Get:function(sname){
        if(!sname){
            return this._bindData;
        }
        if(typeof(sname)!='string' || sname.endsWith('counter') || sname.endsWith('__del')){
            return;
        }
        //sname.startsWith('/bom/') && console.error(sname);
        var name=sname.Trim();
        name=name.Trim('/');
        if(name===''){
            return this._bindData;
        }
        name=name.split('/');
        this.__Lock();  
        var oname ="";
        var obj = [['/',this._bindData,null]];
        for(var i=0,len=name.length;i<len;i++){
            if(name[i]==='__del'){
                console.error('错误的id',sname);
                return undefined;
            }
            if(name[i]=='length'){
                this._setcount--;
                if(obj[i][1] && typeof(obj[i][1])=='object'){
                    //console.log(obj[i][1].length);
                    return obj[i][1].length;
                }else{
                    return 0;
                }
            }
            if(name[i]=='counter'||name[i]=='counterAll'){
                this._setcount--;
                if(obj[i][1] && typeof(obj[i][1])=='object'){
                    //console.log(obj[i][1].length);
                    return obj[i][1][name[i]];
                }else{
                    return 0;
                }
            }
            if(name[i]==='__value'){
                //this._setcount--;
                obj[i+1]=obj[i];
                continue;
            }           
            if(name[i]==='__id'){
                //sname.startsWith('/bom/') && console.error(sname,obj[i][0]);
                this._setcount--;
                return obj[i][0];
            }
            if(name[i]=='__father_id'){
                this._setcount--;
                if(i<1){
                    return undefined;
                }else{
                    return obj[i-1][0];
                }
            }
            if(name[i]=='__father'||name[i]=='..'){
                if(i<1){
                    this._setcount--;
                    return undefined;
                }else{
                    obj[i+1]=obj[obj[i][2]];
                    continue;
                }
            }
            if(obj[i][1]===null || typeof(obj[i][1])!='object'){
                obj[obj[i][2]][1][obj[i][0]] = {};
                obj[i][1]=obj[obj[i][2]][1][obj[i][0]];
            }
            this.__Bind(oname,obj[i][1],name[i]);
            oname = oname + "/" + name[i];
            obj[i+1]=[name[i],obj[i][1][name[i]],i];
        }
        this._setcount--;
        return obj[name.length][1];
    },
    
    
    __NewBindArray:(function(){
		function va(name,_this){
			this.__name=name;
			this.__this=_this;
            this.__prop=this;
            this.__orderBy__ = null;
            this.__refresh__ = false;
		};
		va.prototype={
			__type__:'BindArray',
            //tofirst为true，则显示到第一行
			push:function(obj){
				if(obj===undefined){
					return;
				}
                Array.prototype.push.call(this,obj);
                var i = this.length-1;
                this.__this.__Bind(this.__name,this,i,obj);
                this.refresh();
                return i;
			},
            unshift:function(obj){
                if(obj===undefined){
					return;
				}
                Array.prototype.unshift.call(this,obj);
                this.each(function(i,v){
                    var a=Object.getOwnPropertyDescriptor(this,i);
                    if(!a || !a.set){
                        this.__this.__Bind(this.__name,this,i,v);
                    }
                },this);
                this.refresh();
                return this.length;
            },         
            del:function(i){
                var lastO = this[i];
                this.splice(i,1);
                //delete(this[i]);
                this.refresh();
                return lastO;
			},            
            Set:function(name,obj){
                return this.__this.Set(this.__name+'/'+name,obj);
            },
            Get:function(name){
                return this.__this.Get(this.__name+'/'+name);
            },
            refresh:(function(){             
                function run(){
                    this.__this.__Lock();
                    this.each(function(i,v){
                        var a=Object.getOwnPropertyDescriptor(this,i);
                        if(!a || !a.set){
                            this.__this.__Bind(this.__name,this,i,v);
                        }
                    },this);
                    this.__this.__Unlock(this.__name,this);
                }
                return function(){
                    if(this.__refresh__){
                        return;
                    }
                    this.__prop.__refresh__ = true;
                    var _this = this;
                    setTimeout(function(){
                        run.call(_this);
                        _this.__prop.__refresh__ = false;
                    },5);
                }
            })(),
            setOrderBy:function(value){
                this.__prop.__orderBy__ = value;    
            },
            getOrderBy:function(orderBy){
                if(!orderBy){
                    if(!this.__prop.__orderBy__){
                        return null;
                    }
                    orderBy = this.__prop.__orderBy__;
                }
                if(typeof(orderBy)!='string'){
                    return orderBy;
                }                
                var data = {};
                var desc  = orderBy.split(' ');
                orderBy=desc[0];
                this.each(function(k,v){
                    var vname = k+'/'+orderBy;
                    var ov = this.Get(vname);
                    if(data[ov]===undefined){
                        data[ov]=[];
                    }
                    data[ov].push(k);
                },this);
                var value2 = [];
                data.each(function(k,v){
                    v.each(function(kk,vv){
                        value2.push(vv);
                    },this);
                },this);
                if(desc[1]=='DESC'){
                    var k=value2.length;
                    data=[];
                    while(k-->0){
                        data.push(value2[k]);
                    }
                    value2 = data;
                }
                return value2;
            },
            setCounter:function(counter,counterAll){
                //console.log(counter,counterAll);
                this.__prop.counter =counter;
                this.__prop.counterAll =counterAll;
            },
        };
        Object.setPrototypeOf(va.prototype, Array.prototype);   
        return function(name){
            var obj = [];
            Object.setPrototypeOf(obj,new va(name,this));
			return obj;
		}		
	})(),
    __NewIndexArray:(function(){
        function va(name,_this){
			this.length=0;
			this.__name=name;
			this.__this=_this;
			this.__prop=this;
            this.__orderBy__ = null;
		};
		va.prototype={
			__type__:'indexArray',
            //tofirst为true，则显示到第一行
			push:function(id,obj){
				if(obj===undefined){
					obj = id;
                    id  = J4obj.GetOnlyId();
				}
                if(obj===undefined){
					return;
				}
                if(!id && id!==0){
                    id=J4obj.GetOnlyId();
                }
                this[id] = obj;
                var a=Object.getOwnPropertyDescriptor(this,id);
                if(!a || !a.set){
                    //this.__this.__Lock();
                    this.__prop.length++;
                    this.__this.__Bind(this.__name,this,id,obj);
                    //this.__this.__Unlock(this.__name,this);
                }
                this.refresh();
                //console.log('push',id,this.__name);
                return id;
			}, 
            unshift:function(id,obj){
				this.push(id,obj);
                return id;
			},             
            del:function(i){
				if(typeof(this[i])=='undefined'){
					return;
				}
                //this.__this.__Lock();
                var lastO = this[i];
				var name=this.__name+'/'+i;
                delete(this[i]);
                this.__prop.length--;
                //console.log(i);
                //this.__this.__Unlock(name,undefined,lastO);
                this.refresh();
                return lastO;
			},
            Set:function(name,obj){
                return this.__this.Set(this.__name+'/'+name,obj);
            },
            Get:function(name){
                return this.__this.Get(this.__name+'/'+name);
            },
            refresh:(function(){
                var _run = false;               
                function run(){
                    this.__this.__Lock();
                    var n = 0;
                    this.each(function(i,v){
                        var a=Object.getOwnPropertyDescriptor(this,i);
                        if(!a || !a.set){
                            this.__this.__Bind(this.__name,this,i,v);
                        }
                        n++;
                    },this);
                    this.__prop.length = n;
                    this.__this.__Unlock(this.__name,this);
                }
                return function(){
                    if(_run){
                        return;
                    }
                    _run = true;
                    var _this = this;
                    setTimeout(function(){
                        run.call(_this);
                        _run = false;
                    },5);
                }
            })(),
            __setLength:function(n){
                //console.log('__setLength',n,this.__name);
                this.__prop.length = n;
            },
            setOrderBy:function(value){
                this.__prop.__orderBy__ = value;    
            },
            getOrderBy:function(orderBy){
                if(!orderBy){
                    if(!this.__prop.__orderBy__){
                        return null;
                    }
                    orderBy = this.__prop.__orderBy__
                }
                if(typeof(orderBy)!='string'){
                    return orderBy;
                }                
                var data = {};
                var desc  = orderBy.split(' ');
                orderBy=desc[0];
                this.each(function(k,v){
                    var vname = k+'/'+orderBy;
                    var ov = this.Get(vname);
                    if(data[ov]===undefined){
                        data[ov]=[];
                    }
                    data[ov].push(k);
                },this);
                var value2 = [];
                data.each(function(k,v){
                    v.each(function(kk,vv){
                        value2.push(vv);
                    },this);
                },this);
                if(desc[1]=='DESC'){
                    var k=value2.length;
                    data=[];
                    while(k-->0){
                        data.push(value2[k]);
                    }
                    value2 = data;
                }
                return value2;
            },
            setCounter:function(counter,counterAll){
                this.__prop.counter =counter;
                this.__prop.counterAll =counterAll;
            },
		};
        Object.setPrototypeOf(va.prototype, Object.prototype);   
        return function(name){
            var obj = {};
            Object.setPrototypeOf(obj,new va(name,this));
			return obj;
		}	
    })(),
    
    //兼容方便访问
    set data(v){
        this.Set(v);
    },
    get data(){
        return this._bindData;
    },
    
}
J4.DataSet = function(data){
    return new DataSet(data);
}
//html变化时执行该函数触发事件
function domReset(dom){
    if(J4.Resize){
        J4.Resize(dom);
    }
    if(J4.PlugRun){
        J4.PlugRun({
            type:'domInit',
            target:dom,
            srcElement:dom,
            eachNode:function(className,fn,_this){
                dom.eachFather(className,fn,_this);
            },
        });
    }
    J4.event('domReset').run(dom);
}
function Dom(html,dataSet){
    this._notActive=false;
    this._enableWatch=true;
    this.oid = J4.GetOnlyId();
    this.isChangeList=[];
    this.subDom = {};
    this.modules = {};
    //this.event = J4.Event();//view.event;
    if(html){
        this.SetHtml(html);
    }
    if(dataSet){
        this.SetData(dataSet);
    }
}
Dom.prototype = {
    __type__:'J4Dom',
    get data(){
        return this.dataSet.data;
    },
    set data(v){
        this.dataSet.data = v;
    },
    SetData:function(dataSet){
        if(!dataSet || typeof(dataSet)!='object'){
            return;
        }
        if(dataSet.__type__!='DataSet'){
            dataSet = J4.DataSet(dataSet);
        }
        if(this.dataSet){
            if(this.dataSet.oid == dataSet.oid){
                return;
            }
            this.dataSet.removeCallBack(this.oid);
        }
        this.dataSet = dataSet;       
        this.dataSet.change(this.oid,function(name,o,lastO){
            if(this.cfgObj && this.cfgObj.watch && this._enableWatch){
                this.cfgObj.watch.call(this,name,o,lastO);
            }
            if(!this.__waitComputed && !name.startsWith('/$') && this.cfgObj && this.cfgObj.computed){
                if(!this.data['$']){
                    this.data.Set('$',{});
                }
                this.setTimeout(function(){
                    this.cfgObj.computed.each(function(i,v){
                        this.data['$'][i] = v.call(this,name,o,lastO);
                    },this);
                    this.__waitComputed = false;
                },20);
                this.__waitComputed = true;
            }
            this.DataChange(name);
        },this);  
        this.dataSet.runCallback('/',this.data,null);     
    },
    readData:(function(){
        function _readData(ddom,v){
            var s = v.split('/');
            var sdom = ddom;
            var isf = false;
            var n = 0;
            //console.log(s);
            s.each(function(i,d){
                if(d!='..'){
                    return false;
                }
                n+=3;
                isf = false;
                if(sdom.tplFather){
                    sdom = sdom.tplFather;
                }else{
                    sdom = sdom.parentNode || sdom.parentElement;
                }              
                while(sdom && sdom.nodeName!='BODY'){
                    if(sdom.bindAttr && sdom.bindAttr['list_father']){
                        isf = true;
                        break;
                    }
                    if(sdom.tplFather){
                        sdom = sdom.tplFather;
                    }else{
                        sdom = sdom.parentNode || sdom.parentElement;
                    }
                };
                if(!isf){
                    return false;
                }
            });
            v = v.substr(n);
            if(isf){
                //console.log(sdom.bindAttr['list_father'].data.a+'/'+v);
                return sdom.bindAttr['list_father'].data.a+'/'+v;
            }else{
                return '/'+v;
            }
        }
        return function(dom,calc,counter,counterAll,__id){
            var exp = calc.exp;
            var data = J4.CopyObj(calc.data);
            data.each(function(i,v){
                if(v.startsWith('../')){
                    v = _readData.call(this,dom,v);
                    //dom.J4bind_datalist[v]=true;
                }
                if(v.endsWith("counter")){
                    data[i]=this.Get(v.substr(0,v.length-8));
                    if(!data[i]||data[i].counter===undefined){
                        data[i] = counter;
                    }else{
                        data[i]=data[i].counter;
                    }
                    //console.log(data[i]);
                }else if(v.endsWith("counterAll")){
                    data[i]=this.Get(v.substr(0,v.length-11));
                    if(!data[i]||data[i].counter===undefined){
                        data[i] = counterAll;
                    }else{
                        data[i]=data[i].counter;
                    }
                }else{
                    data[i]=this.Get(v);
                }
            },this); 
            //data.__id = __id;
            //data.counter = counter;
            //data.counterAll = counterAll;
            //console.log(exp.srcCode,calc.data,data);
            return exp.call(this,data);
        }
    })(),
    enableWatch:function(){
        this._enableWatch=true;
    },
    disableWatch:function(){
        this._enableWatch=false;
    },
    Get:function(name){
        return this.dataSet.Get(name);  
    },   
    Set:function(name,obj){
        return this.dataSet.Set(name,obj);
    },  
    disableChange:function(){
        this._notActive = true; 
        console.error('禁止更新',this);
    },
    enableChange:function(){
        this._notActive = false;
        this.DataChange('/');      
    },
    SetHtml:function(name,html){
        if(arguments.length==1){
            html = name;
            name = false;
        }
        var newDiv;
        if(!html){
            console.error('创建dom失败!');
            return;
        }else if(typeof(html)=='object' && html.__type__=='Node'){ 
            newDiv=html;
        }else if(typeof(html)=='string'){
            newDiv=document.createElement("div");
            newDiv.resetChildren(html);
        }else{
            console.error('创建dom失败!');
            return null;
        }     
        //newDiv.addClass("J4-view");
        if(newDiv.hasClass('window')||newDiv.getAttribute('J4window')!=null){
            newDiv.removeClass('window');
            var c = newDiv.getAttribute('class');
            var header = html.getElementsByClassName('J4-win-header')[0];
            var content = html.getElementsByClassName('J4-win-content')[0];
            var footer = html.getElementsByClassName('J4-win-footer')[0];
            if(!header){
                header = newDiv.getAttribute('title');
            }
            if(!content){
                content = newDiv;
                newDiv.removeAttribute('subDom');
                newDiv.removeAttribute('title');
            }
            newDiv = J4.win(header,content,footer).init();
            newDiv.addClass(c);
            newDiv.boxid = 'window';
        }
        //newDiv.eventthis = this;
        newDiv.oid=this.oid;
        newDiv.modbox = this;
        if(name){
            this.subDom[name] = newDiv;
        }else{
            this.dom = newDiv;
        }
        this.InitDom(newDiv);
        if(this.dataSet){
            this.DataChange('/'); 
        }
        return newDiv
    },    
    
    InitDom:(function(){   
        function getData(calc){
            var exp = calc.exp;
            var data = J4.CopyObj(calc.data);
            data.each(function(i,v){
                data[i]=this.Get(v);
            },this); 
            return exp.call(this,data);
        }
		function _runEvent(dom,fname,argu,data,e){
            var _this = this;
            if(!_this[fname]||typeof(_this[fname])!='function'){
                //console.log(_this);
                console.error('事件方法不存在:'+fname,_this);
                return;
            }
            var value = e.__value;
			argu = J4.CopyObj(argu);
            argu.each(function(i,v){
                if(!v){
                    return;
                }
                if(v==='event'){
                    argu[i] = e;
                    return;
                }else if(v==='dom' || v==='this' || v==='self'){
                    argu[i]=dom;
                    return;
                }else if(v==='value'){
                    if(value===undefined){
                        value = dom.getVal();
                    }
                    argu[i]=value.value;
                    return;
                }else if(v==='valueinfo'){
                    if(value===undefined){
                        value = dom.getVal();
                    }
                    argu[i]=value;
                    return;
                }else if(v==='error'){
                    if(value===undefined){
                        value = dom.getVal();
                    }
                    argu[i]=value.err;
                    return;
                }else if(v==='true'){
                    argu[i]=true;
                    return;
                }else if(v==='false'){
                    argu[i]=false;
                    return;
                }else if(v==='null'){
                    argu[i]=null;
                    return;
                }else if(v.startsWith("'")&& v.endsWith("'")){
                    argu[i] = v.substr(1,v.length-2);
                    return;
                }else if(v.startsWith('"')&& v.endsWith('"')){
                    argu[i] = v.substr(1,v.length-2);
                    return;
                }else if(!isNaN(v)){
                    argu[i] = v*1;
                    return;
                }else{
					//v = v.toLowerCase();
					if(!data[v]){
						console.error('事件参数不存在:J4on'+e.type+'='+fname+'('+v+')');
						return;
					}
					argu[i] = getData.call(_this,data[v]); 
				}				
            }); 
            e.__value = value;
            return _this[fname].apply(_this,argu);
        }
        function runEvent(e,type){
            if(J4.PlugRun(e,type)===false){
                return;
            }
            var dom = this;
            var ename = type?type:e.type;
            var eobj = dom.eventlist;
            var _this = dom.eventthis;
            var data = dom.eventdata;
            var value = e.__value;             
            if(ename=='change'){
                if(value===undefined){
                    value = dom.getVal();
                    e.__value = value;
                }
                //dom.setdValue = value;
                if(eobj && eobj['changebefor']){
                    eobj['changebefor'].each(function(i,v){
                        var fname = v.name;
                        var argu = J4.CopyObj(v.argu);
                        if(_runEvent.call(_this,dom,fname,argu,data,e)===false){
                            if(e.preventDefault){
                                e.preventDefault();
                                e.stopPropagation();
                            }
                            return false;
                        }
                    },this);
                }              
                if(value.error && eobj && eobj['check']){
                    eobj['check'].each(function(i,v){
                        var fname = v.name;
                        var argu = J4.CopyObj(v.argu);
                        var err=_runEvent.call(_this,dom,fname,argu,data,e);
                        if(err){
                            value.error = err;
                            value.value = '';
                            if(e.preventDefault){
                                e.preventDefault();
                                e.stopPropagation();
                            }
                            return false;
                        }
                    });
                }
                if(dom.bindAttr && dom.bindAttr['errorinput']){
                    if(!value.error){
                        value.error='';
                    }
                    _this.ErrorInput(dom,value.error,value);
                }else if(value.error){
                    J4.Msg('输入错误',value.error);
                }
                if(value.error){
                    dom.setVal(value.value);
                }
                if(dom.bindAttr && dom.bindAttr['input']){
                    _this.DataInput(dom,value.value,value);
                }
                //dom.lastValue = value.value;
            }else if(ename=='blur'){
                if(dom.getAttribute('contenteditable')){
                    runEvent.call(dom,e,'change');
                }
            }else if(ename=='drop'){
                e.__value = {
                    type:'files',
                    value:e.dataTransfer.files,
                    err:''
                }
            }else if(ename=='paste'){
                value = {};
                var cli=e.clipboardData?e.clipboardData:e.originalEvent.clipboardData; 
                if(cli.types.length==0){
                    value = null;
                }else if(cli.types[0]=='Files'){
                    var items=cli.items; 
                    var len = items.length;
                    var filelist=[];
                    var i=0;
                    var file;
                    while (len--) {
                        file = items[len];
                        if (file.getAsFile){
                            file = file.getAsFile();
                        }
                        //console.log(file);
                        if (file && file.size <= 0){
                            console.error("空白的文件",items[len]);
                            continue;//空文件忽略
                        } 
                        if(file){
                            filelist.push(file);
                            rs=false;
                        }
                    }  
                    //console.log(filelist);
                    value.type='file';
                    value.value=filelist;                                
                }else{
                    value.txt=cli.getData('text/plain').Trim();
                    value.html=cli.getData('text/html').Trim();
                    value.type=(txt==html||!html)?'text':'html';
                    value.value=(txt==html||!html)?txt:html;
                }
            }
            if(e.__value){
                value = e.__value;
            }
            if(eobj && eobj[ename]){
                e.__value = value;
                eobj[ename].each(function(i,v){
                    var fname = v.name;
                    var argu = J4.CopyObj(v.argu);
                    if(_runEvent.call(_this,dom,fname,argu,data,e)===false){
                        if(e.preventDefault){
                            e.preventDefault();
                            e.stopPropagation();
                        }
                        return false;
                    }
                });
                value = e.__value;
            }
            switch(ename){
                case 'click':
                    if(dom.bindAttr && dom.bindAttr['clickinput']){
                        _this.ClickInput(dom);
                    }
                    break; 
                case 'drop':
                    if(dom.bindAttr && dom.bindAttr['filedrop'] && e.preventDefault){
                        e.preventDefault();
                        e.stopPropagation();
                    }
                    break;
            }
        }
        function TurnTreeName(sname){
            if(typeof(sname)!='string'){
                return;
            }
            var name=sname.Trim(' /').split('/');
            var len=name.length;
            var rlen = 0;
            var oname=[];
            name.each(function(i,v){
                if(rlen==0){
                    oname[rlen]=v;
                    rlen++;
                }else if(v=='__father'||v=='..'){                   
                    rlen--;
                }else{
                    oname[rlen]=v;
                    rlen++;
                }
            })
            sname='';
            for(var i=0;i<rlen;i++){
                sname+='/'+oname[i];
            };
            return sname;
        }
        function GetCalcObj(str){//将提取出的表达式简析为表达式对象
            if(typeof(str)!='string'){
                return null;         
            }
            str=str.Trim();
            if(!str){
                return null;
            }
            var not=false;
            if(str.startsWith('!')){//str.substr(0,1)=='!'){
                str=str.Ltrim('!').Trim();
                not=true;
            }
            var exp;
            var vlist={};
            if(str.startsWith('Calc(') && str.endsWith(')')){
                str = str.substring(5,str.length-1);
                var a=false,i,len,v;
                for(i=0,len=str.length;i<len;i++){
                    v = str.charAt(i);
                    if(a){
                        if(a===v && str.charAt(i-1)!=='\\'){
                            a=false;
                            continue;
                        }   
                    }else{
                        if(v===','){
                            break;
                        }else if(v==='"'){
                            a='"';
                        }else if(v==="'"){
                            a="'";
                        }
                    }
                };
                exp=str.substring(0,i);
                if(not){
                    exp='!('+exp+')';
                }
                var enumlist = (i==len)?[]:str.substr(i+1).split(',');
                 //CalcObj = [exp,{}];//类型，表达式，参数
                enumlist.each(function(k,d){
                    var n=d.indexOf('=');
                    if(n==0||n==-1){
                        return;
                    }
                    var id=d.substr(0,n).Trim();
                    vlist[id]=d.substr(n+1).Trim();
                });    
            }else if(str.startsWith('(') && str.endsWith(')')){
                str = str.substring(1,str.length-1);
                var enumlist = [];
                var a=false,i,len,v,lastI=0;
                for(i=0,len=str.length;i<len;i++){
                    v = str.charAt(i);
                    if(a){
                        if(a===v && str.charAt(i-1)!=='\\'){
                            a=false;
                            continue;
                        }   
                    }else{
                        if(v===','){
                            enumlist.push(str.substring(lastI,i));
                            lastI = i+1;
                            //break;
                        }else if(v==='"'){
                            a='"';
                        }else if(v==="'"){
                            a="'";
                        }
                    }
                };
                exp=str.substring(lastI);
                if(not){
                    exp='!('+exp+')';
                }
                enumlist.each(function(k,d){
                    var n=d.indexOf('=');
                    if(n==0||n==-1){
                        return;
                    }
                    var id=d.substr(0,n).Trim();
                    vlist[id]=d.substr(n+1).Trim();
                });   
            }else{
                //var str2=str.Ltrim('!').Trim();
                if(not){
                    exp='!a';
                }else{
                    exp='a';
                }
                vlist['a']=str;
            }
            exp = J4.ExpToFunction(exp);
            return {exp:exp,data:vlist};
        }
        function domAttrBind(dom,bn,exp,sname){
            if(!exp){
                return exp;
            }
            var itemName = exp;
            if(bn=='clickinput' && !exp.startsWith('(') && !exp.startsWith('Calc(')){
                var str = '(';
                var n=0;
                exp.split(';').each(function(i,v){
                    if(!v){
                        return;
                    }
                    v = v.split('=');
                    if(v.length!=2){
                        console.error('错误的表达式:'+exp);
                    }
                    str += 'saveTo_'+i+'='+v[0].Trim()+',a_'+i+'='+v[1]+',';
                    n++;
                });
                str += n+')';
                exp = str;
            }          
            var bv = GetCalcObj(exp);
            if(!bv){
                console.error("错误的绑定",bn,exp);
                return;
            }
            bv.sname = {};
            if(bv.exp=='$'){
                return bv;
            }
            if((bn=='tpl'||bn=='list') && bv.exp.exp!='a'){
                console.error("tpl和list绑定不能使用表达式",bn,exp,bv);
                return;
            }
            bv.data.each(function(i,v){
                if(v.startsWith('__value/')){
                    v = v.substr(8);
                }
                if(v=='counter'){
                    bv.data[i] = v;  
                    v = null;
                }else if(v.startsWith('$')){
                    v ='/$/'+v.substr(1);
                    bv.data[i] = v;
                }else if(v.startsWith('/')){
                    v = TurnTreeName(v);
                    bv.data[i] = v;
                }else if(bn=='list_if' || bn=='printlist_if'){
                    if(v && (v.startsWith('./'))){
                        v=v.Trim('./');
                        if(sname){
                            bv.sname[i]=v;
                            var ssname = sname.Trim('/');
                            v = ssname?(ssname+'/'+v):v;
                        }
                        v = '/'+v;
                        v = TurnTreeName(v);
                        bv.data[i] = v;
                    }else{
                        //v = TurnTreeName(v);
                        //console.log(bv.data);
                        bv.data[i] = v.Trim('/');
                        v = null;
                    }
                }else if(v.startsWith('../')){
                    v = TurnTreeName(v);
                    bv.data[i] = v.Ltrim('/');
                }else{
                    if(sname){
                        bv.sname[i]=v;
                        var ssname = sname.Trim('/');
                        v = ssname?(ssname+'/'+v):v;
                    }
                    v = '/'+v;
                    v = TurnTreeName(v);
                    bv.data[i] = v;
                }  
                if(v && bn && bn!='input' && bn!='filedrop' 
                    && bn!='clickInput' && bn!='errorinput'){
                    dom.J4bind_datalist[v]=true;
                }
            },this);
            if(bn=='tpl'){
                dom.eachChildren(function(dom){
                    if(dom.modbox){
                        return false;
                    }
                    return _initDom.call(this,dom,bv.data['a']);
                },this);
                //dom.bindfather = sname;
                return bv;
            }else if((bn == 'list'|| bn=='while') && !dom.J4bind_tpl){
                var list = document.createElement('div');
                list.tplFather = dom;
                dom.unLoopList = [];
                dom.eachChildren(function(v){
                    if(v.nodeType!=3 && v.getAttribute('unLoop')!=null){
                        dom.unLoopList.push(v);
                        return false;
                    }
                    v.tplFather = dom;
                    list.appendChild(v);
                    return false;
                });
                dom.J4bind_tpl=list;
                dom.J4bind_children=[];
                //dom.bindfather = sname;
            }else if(bn=='input'){
                var dtype = dom.nodeName;
                if(dtype!='SELECT'&&dtype!='INPUT'&&dtype!='TEXTAREA'&&
                        !dom.hasClass('inputBool')&&dom.getAttribute('contenteditable')===null){
                    dom.setAttribute('contenteditable',true);
                }
            }
            return bv;
        }
        var reg = /\{\{(.*?)\}\}/;
        function readTextBind(str,start,len){
            var a=false,i,v;
            for(i=start+2;i<len;i++){
                v = str.charAt(i);
                if(a){
                    if(a===v && str.charAt(i-1)!=='\\'){
                        a=false;
                        continue;
                    }   
                }else{
                    if(v==='"'){
                        a='"';
                    }else if(v==="'"){
                        a="'";
                    }else if(v==='}'){
                        i++;
                        v = str.charAt(i);
                        if(v==='}'){
                            i++;
                            break;
                        }
                    }
                }
            }
            return str.substring(start,i);
        }
        function readText(text){
            var list=[];
            var now=0;
            var len = text.length;
            var t;
            for(var i=0;i<len;i++){
                if(text.charAt(i)=='{'){
                    if(text.charAt(i+1)=='{'){
                        if(i>now){
                            list.push(text.substring(now,i));
                        };
                        var t = readTextBind(text,i,len);
                        list.push(t);
                        i+=t.length-1;
                        now = i+1;
                    }
                }
            }
            if(i>now){
                list.push(text.substring(now,i));
            };
            return list;
        }
        function initTextNode(dom,sname){
            if(!reg.test(dom.textContent)){
                    return false;
            }
            //console.log({aa:dom});
            dom = dom.parentElement?dom.parentElement:dom.parentNode;
            if(!dom.bindAttr){
                dom.bindAttr={};
            }
            dom.bindAttr.textList=[];
            var textList = readText(dom.textContent);
            if(!dom.J4bind_datalist){
                dom.J4bind_datalist = {};
            }
            textList.each(function(i,v){
                if(v.startsWith('{{')&&v.endsWith('}}')){
                    v=v.Trim('{}');
                    dom.bindAttr.textList.push(domAttrBind.call(this,dom,'textNode',v,sname));
                }else{
                    dom.bindAttr.textList.push(v);
                }
            },this);
            //console.log(textList);
            //dom.bindAttr.textList=textList;
            return false;
        }
        function useMod(dom){
            var modlist = dom.getAttribute('useMod');
            if(modlist && this.cfgObj && this.cfgObj.modules){
                dom.removeAttribute('useMod');
                modlist=modlist.split(/,|;/g);
                var mods = this.cfgObj.modules;
                modlist.each(function(i,v){
                    if(!mods[v] && mods[v].__type__!='Module'){
                        return;
                    }
                    var sv = v.split('.');
                    v=sv[0];
                    var mod = this[v]; 
                    if(!mod){ //|| mod.__type__=='Module'                      
                        this[v] = mods[v].create();
                        //this.modules[v] = this[v];
                        mod = this[v]; 
                    }
                    if(!mod||mod.__type__!='J4Dom'){
                        console.error('引用的类无法实例化');
                        return;
                    }
                    if(sv[1]){
                        mod.subDomAppendTo(sv[1],dom); 
                    }else{
                        mod.appendTo(dom); 
                    }                    
                },this);
                return false;
            }
            //模块绑定（即将该dom节点关联到其他模块处理，而不是用当前模块处理
            var linkMod = dom.getAttribute('linkMod');
            if(linkMod && this.cfgObj && this.cfgObj.modules){
                dom.removeAttribute('linkMod');
                var mods = this.cfgObj.modules;
                if(!mods[linkMod]){
                    return false;
                }
                var name = J4.GetOnlyId();
                dom.setAttribute('modName',name);
                mods[linkMod].SetHtml(name,dom);
                //J4.event('domReset').run(dom);
                domReset(dom);
                return false;
            }
        }
        function initOldBind(dom,bind,sname){//旧的绑定写法，新项目不推荐使用
            bind=bind.Trim('; ');
            if(!bind || bind=='-'){
                return {};
            }
            //console.log(bind);
            bind=bind.split(';');//这个地方有漏洞,应该按照字节流来进行分割
            var bn,bv;
            var tpl=false;
            var rs={};
            bind.each(function(i,v){
                v=v.Trim();
                if(!v){
                    return;
                }
                var n=v.split(':')[0].length;
                bn=v.substr(0,n).Trim().toLowerCase();
                bv=v.substr(n+1).Trim();
                if(!bn || !bv){
                    return;// false;
                }
                if(bn=='inputbind'){
                    bn = 'input';
                }
                rs[bn]=bv;
            });
            //console.log(dom,rs,bind);
            return rs;
        }
        function reInitDom(dom,sname){
            if(sname && dom.bindsname){
                dom.J4bind_datalist={};
                if(dom.bindAttr){
                    dom.bindAttr.each(function(i,v){
                        if(i=='textList'){
                            v.each(function(n,s){
                                if(!s || !s.data){
                                    return;
                                }
                                s.data.each(function(k,d){
                                    if(d=='counter'){
                                        return;
                                    } 
                                    if(s.sname[k]){
                                        d =s.sname[k];
                                        var ssname = sname.Trim('/');
                                        d = ssname?(ssname+'/'+d):d;
                                        d = TurnTreeName('/'+d);
                                        s.data[k] = d;
                                    }    
                                    if(d.startsWith('/')){
                                        dom.J4bind_datalist[d]=true;
                                    }
                                },this);
                            });
                        }else if(i=='list_father'){
                            v.data['a'] = sname;
                            //console.log(sname);
                        }else{
                            v.data.each(function(k,d){
                                if(d=='counter'){
                                    return;
                                } 
                                if(v.sname[k]){
                                    d =v.sname[k];
                                    var ssname = sname.Trim('/');
                                    d = ssname?(ssname+'/'+d):d;
                                    d = TurnTreeName('/'+d);
                                    v.data[k] = d;
                                }    
                                if(d.startsWith('/')){
                                    dom.J4bind_datalist[d]=true;
                                }
                            },this);
                        }
                    },this);
                }
                if(dom.eventdata){
                    dom.eventdata.each(function(i,v){
                        v.data.each(function(k,d){
                            if(d=='counter'){
                                return;
                            } 
                            if(v.sname[k]){
                                d =v.sname[k];
                                var ssname = sname.Trim('/');
                                d = ssname?(ssname+'/'+d):d;
                                d = TurnTreeName('/'+d);
                                v.data[k] = d;
                            }    
                            if(d.startsWith('/')){
                                dom.J4bind_datalist[d]=true;
                            }
                        },this);
                    },this);
                }
                dom.bindsname = sname;
            }
            if(dom.bindAttr && (dom.bindAttr['tpl']||dom.bindAttr['list']||dom.bindAttr['while'])){
                return false;
            }
        }       
        function setPlug(dom,plugList){
            var plugins = {};
            plugList.each(function(i,d){
                if(!d){
                    return;
                }    
                var argu = [];
                if(d){
                    d = d.split(',');
                    d.each(function(n,m){
                        if(!m){
                            return;
                        }
                        argu.push(m);                           
                    });  
                }                
                plugins[i] = argu;
            },this);
            if(!plugins.isEmpty()){
                dom.plugins = plugins;
            }
        }
        function setEvent(dom,eventList,J4data,sname){
            var elist={};
            eventList.each(function(i,d){
                if(!d){
                    return;
                }               
                var sli = [];
				//这里如果参数中字符串有分号会出问题,需要优化分割方案
                d.split(';').each(function(k,v){
                    v = v.split('(');
                    var name = v[0];
                    if(!name){
                        return;
                    }
                    var argu=[];
                    if(v[1]){
						v[1]=v[1].Trim();
						if(!v[1].endsWith(')')){
							console.error("事件绑定缺少必要的后括号:"+v);
						}
                        v = v[1].Rtrim(')').split(',');
                        v.each(function(n,m){
                            switch(m){
                                case 'dom':
                                case 'event':
                                case 'this':
                                case 'self':
                                case 'value':
                                case 'valueinfo':
                                case 'error':
                                case 'true':
                                case 'false':
                                case 'null':
                                    break;
                                default:
                                    /*if(m && !m.startsWith('"') && !m.startsWith("'") && !J4data[m]){
                                        if(!isNaN(m)){
                                            J4data[n]=m;
                                        }else{      
                                            n = 'a'+n;
                                            J4data[n]=domAttrBind.call(this,dom,null,m,sname);
                                            m=n;
                                        }
                                    }*/ 
									if(m && !m.startsWith('"') && !m.startsWith("'") && isNaN(m) && !J4data[m]){
										J4data[m]=domAttrBind.call(this,dom,null,m,sname);
									}
                                    break;
                            }
                            argu.push(m);                           
                        });
                    }
                    sli.push({
                        name:name,
                        argu:argu,
                    });
                });
                if(sli.length>0){
                    elist[i.substr(2)] = sli;
                    dom[i] = runEvent;
                }
            },this);
            if(!elist.isEmpty()){ 
                //elist.data = J4data;
                //elist._this = this;
                dom.eventlist = elist;
            }
            dom.eventthis = this;   
            dom.eventdata = J4data;            
        }
        function turnBind(dom,bindList){
            if(bindList['bind']){
                initOldBind(dom,bindList['bind']).each(function(i,v){
                    if(i=="class"){
                        bindList['class_'+J4.GetOnlyId()]=v;
                    }else{
                        bindList[i]=v;
                    }
                },this);
                delete(bindList['bind']);
            }
            if(bindList['if']){
                //bindList['_if'] = bindList['if'];
                bindList['show'] = bindList['if'];
                delete(bindList['if']);
                //console.log("J4if已经转为J4show");
            }
            if(bindList['while']){
                bindList['_while'] = bindList['while'];
                delete(bindList['while']);
            }
            if(bindList['list']||bindList['tpl']){
                bindList['list_father'] = '__value/';
            }
            if(bindList.inout){
                if(bindList.inout.startsWith('Calc(')){
                    console.error('inout绑定不能使用表达式');
                }
                bindList.input = bindList.inout;
                bindList.value = bindList.inout;
                delete(bindList.inout);
            }
            var t = bindList["class"];
            if(t){
                delete(bindList["class"]);
                var enumlist=[];
                var a=false,i,len,v,lastI=0;
                for(i=0,len=t.length;i<len;i++){
                    v = t.charAt(i);
                    if(a){
                        if(a===v && t.charAt(i-1)!=='\\'){
                            a=false;
                            continue;
                        }   
                    }else{
                        if(v===';'){
                            enumlist.push(t.substring(lastI,i));
                            lastI = i+1;
                        }else if(v==='"'){
                            a='"';
                        }else if(v==="'"){
                            a="'";
                        }
                    }
                };
                enumlist.push(t.substring(lastI,i));      
                enumlist.each(function(i,v){
                    var cname = v.split(':');
                    cname = cname[0];
                    v = v.substring(cname.length+1);
                    bindList['class-'+cname]=v;
                });         
            }
            t = bindList["style"];
            if(t){
                delete(bindList["style"]);
                var enumlist=[];
                var a=false,i,len,v,lastI=0;
                for(i=0,len=t.length;i<len;i++){
                    v = t.charAt(i);
                    if(a){
                        if(a===v && t.charAt(i-1)!=='\\'){
                            a=false;
                            continue;
                        }   
                    }else{
                        if(v===';'){
                            enumlist.push(t.substring(lastI,i));
                            lastI = i+1;
                        }else if(v==='"'){
                            a='"';
                        }else if(v==="'"){
                            a="'";
                        }
                    }
                };
                enumlist.push(t.substring(lastI,i));      
                enumlist.each(function(i,v){
                    var cname = v.split(':');
                    cname = cname[0];
                    v = v.substring(cname.length+1);
                    bindList['style-'+cname]=v;
                });         
            }
            t = bindList["j4highlighttext"];
            if(t){
                var enumlist=[];
                var a=false,i,len,v,lastI=0;
                for(i=0,len=t.length;i<len;i++){
                    v = t.charAt(i);
                    if(a){
                        if(a===v && t.charAt(i-1)!=='\\'){
                            a=false;
                            continue;
                        }   
                    }else{
                        if(v===';'){
                            enumlist.push(t.substring(lastI,i));
                            lastI = i+1;
                        }else if(v==='"'){
                            a='"';
                        }else if(v==="'"){
                            a="'";
                        }
                    }
                };
                enumlist.push(t.substring(lastI,i));      
                enumlist.each(function(i,v){
                    var cname = v.split(':');
                    cname = cname[0];
                    v = v.substring(cname.length+1);
                    bindList['highlight_'+cname]=v;
                });         
            }           
        }
        function _initDom(dom,sname){  
            dom.bindsname = sname;
            //dom.bindfather = father;
            if(dom.J4bind_datalist){ //如果存在说明对象已经初始化过，那就只修改sname来更新绑定
                return reInitDom.call(this,dom,sname);
            }
            if(dom.nodeType==3){//文本节点
                return initTextNode.call(this,dom,sname);
            }
            if(false===useMod.call(this,dom)){//模块引用和模块绑定             
                return false;
            }
            var bindList={};
            var eventList={};
            var J4data = {};
            var plugList = {};
            var removelist = [];
            var router = false;
            dom.attributes.each(function(i,v){
                var name = v.name.Trim();
                var value = v.value.Trim(' ;');
                //console.log(value);
                if(!value){
                    return;
                }
                if(name.startsWith('j4')){  
                    removelist.push(name);
                    if(name.startsWith('j4on')){
                        name = name.substr(2);
                        eventList[name]=value;
                    }else if(name.startsWith('j4data-')){
                        name = name.substr(7);
                        J4data[name] = domAttrBind.call(this,dom,null,value,sname);
                    }else if(name.startsWith('j4plug-')){
                        name = name.substr(7);
                        plugList[name] = value;                       
                    }else{
                        name = name.substr(2);
                        bindList[name]=value;
                    }             
                }else if(name=='router'){
                    router = value;    
                    removelist.push(name);
                }
            },this);
            if(!J4.DEBUG){
                removelist.each(function(i,v){
                    dom.removeAttribute(v); 
                });
            }
            if(router){
                if(eventList['onclick']){
                    eventList['onclick']+=';Router("'+router+'")';
                }else{
                    eventList['onclick']='Router("'+router+'")';
                }
            }
            setPlug.call(this,dom,plugList);//插件绑定
            setEvent.call(this,dom,eventList,J4data,sname);//事件绑定
            turnBind.call(this,dom,bindList);//属性转换和兼容
            
            var blist = {};
            dom.J4bind_datalist = {};
            bindList.each(function(i,v){
                //dom.removeAttribute('J4'+i);
                if(!v){
                    return;
                }
                var b = domAttrBind.call(this,dom,i,v,sname);
                if(!b){
                    return;
                }
                blist[i]=b;
            },this); 
            var elist = dom.eventlist;
            if(!elist){
                elist = {};
            }
            if(!blist.isEmpty()){
                if((blist['input'] || elist['changebefor']) && !elist['change']){
                    dom.onchange = runEvent;
                    if(!elist['blur']){
                        dom.onblur = runEvent;
                    }
                }
                if(blist['clickinput'] && !elist['click']){
                    dom.onclick = runEvent;
                }
                if(blist['filedrop']&& !elist['drop']){
                    dom.ondrop = runEvent;
                }
                //dom.addClass("J4bind");
                dom.bindAttr = blist;
                if(blist['tpl']){
                    return false;
                }
            }            
        }
        return function(tdom,sname){
            if(_initDom.call(this,tdom,sname)===false){
                return;
            }
            tdom.eachChildren(function(dom){
                if(dom.modbox){
                    return false;
                }
                return _initDom.call(this,dom,sname);
            },this);
        }
    })(),   
    DataChange:(function(){ //return function(name,value,lastValue)
        function _readData(ddom,v){
            var s = v.split('/');
            var sdom = ddom;
            var isf = false;
            var n = 0;
            //console.log(s);
            s.each(function(i,d){
                if(d!='..'){
                    return false;
                }
                n+=3;
                isf = false;
                if(sdom.tplFather){
                    sdom = sdom.tplFather;
                }else{
                    sdom = sdom.parentNode || sdom.parentElement;
                }            
                while(sdom && sdom.nodeName!='BODY'){
                    if(sdom.bindAttr && sdom.bindAttr['list_father']){
                        isf = true;
                        break;
                    }
                    if(sdom.tplFather){
                        sdom = sdom.tplFather;
                    }else{
                        sdom = sdom.parentNode || sdom.parentElement;
                    }
                };
                if(!isf){
                    return false;
                }
            });
            v = v.substr(n);
            if(isf){
                return sdom.bindAttr['list_father'].data.a+'/'+v;
            }else{
                return '/'+v;
            }
        }        
        //list单独处理
        function _refreshList(dom,value,sname){    
            if(!value || typeof(value)!='object' || !dom.J4bind_tpl){
                dom.J4bind_children.each(function(i,v){
                    v.each(function(n,sdom){
                        sdom.remove();
                        sdom._isremove = true;
                    });
                });
                return;
            }
            if(value.__type__!='indexArray' && value.__type__!='BindArray'){
                dom.J4bind_children.each(function(i,v){
                    v.each(function(n,sdom){
                        sdom.remove();
                        sdom._isremove = true;
                    });
                });
                return;
            }
            //var father = dom.bindfather;
            var orderBy = null;
            var list_if = dom.bindAttr['list_if'];
            var list_orderBy = dom.bindAttr['list_orderBy'];
            if(list_orderBy){
                /*var exp = list_orderBy.exp;
                var data = J4.CopyObj(list_orderBy.data);
                data.each(function(k,v){
                    if(v.endsWith("counter")){
                        data[k] = dom.J4bind_list_counter;
                    }else{
                        data[k]=this.Get(v);
                    }
                },this);
                orderBy = exp.call(this,data);*/
                orderBy = this.readData(dom,list_orderBy);
            }
            if(!orderBy ){
                orderBy = value.__orderBy__;
            }     
            var list;
            if(orderBy){
                list = value.getOrderBy(orderBy);
            }else{
                list = value;
            }
            var i=0,j=0,len=dom.J4bind_children.length;
            list.each(function(id,dlist){ //行
                if(orderBy){
                    id=dlist;    
                }
                if(dom.bindAttr["printlist_if"]){
                    var data = J4.CopyObj(dom.bindAttr["printlist_if"].data);
                    var datav = {};
                    data.each(function(i,v){
                        //console.log(v);
                        if(v.startsWith('../')){
                            v = _readData.call(this,dom.J4bind_tpl,v);
                            //dom.bindAttr["printlist_if"].data[i]=v;
                            //console.log(v);
                        }else if(!v.startsWith('/')){
                            v = sname+'/'+id+'/'+v;
                        }
                        if(v.endsWith("counter")){
                            data[i] = i;
                        }else{
                            //console.log(v);
                            data[i]=this.Get(v);
                        }
                        datav[i]=v;
                    },this); 
                    data.__id = id;
                    data.counter = i;
                    data.counterAll = i;
                    console.log({
                        'Calc':dom.bindAttr["printlist_if"].exp.srcCode,
                        'bind':dom.bindAttr["printlist_if"].data,
                        'bind2':datav,
                        'data':data,
                        'value':J4.CopyObj(this.readData(dom.J4bind_tpl,dom.bindAttr["printlist_if"],i,j,id)),
                        'value2':dom.bindAttr["printlist_if"].exp.call(this,data),
                        'dom':dom,
                        '_this':this});
                } 
                if(list_if){
                    var data = J4.CopyObj(list_if.data);
                    data.each(function(i,v){
                        if(v.startsWith('../')){
                            v = _readData.call(this,dom.J4bind_tpl,v);
                        }else if(!v.startsWith('/')){
                            v = sname+'/'+id+'/'+v;
                        }
                        if(v.endsWith("counter")){
                            data[i] = i;
                        }else{
                            data[i]=this.Get(v);
                        }
                    },this);
                    if(!list_if.exp.call(this,data)){
                        j++;
                        return;
                    }
                }
                j++;
                //console.log(value);
                //value.setCounter(i,j);
                if(i<len){
                    dom.J4bind_children[i].each(function(n,sdom){
                        sdom.tplFather = dom;
                        this.InitDom(sdom,sname+'/'+id);//子节点在父节点后面更新，属以初始化后不退出节点遍历，那后面遍历到时一定以及初始化
                        dataChange.call(this,sdom,i,j,id);
                        if(sdom._isremove){
                            dom.appendChild(sdom);
                            sdom._isremove = false;
                        }
                    },this);
                }else{
                    dom.J4bind_children[i] = [];
                    var tpl=dom.J4bind_tpl.cloneNode(true);
                    //tpl.tplFather = dom;
                    
                    var a=[];
                    tpl.eachChildren(function(d){
                        d.tplFather = dom;
                        this.InitDom(tpl,sname+'/'+id);
                        a.push(d);
                        return false;
                    },this);
                    a.each(function(k,d){
                        dom.J4bind_children[i].push(d);
                        dataChange.call(this,d,i,j,id);
                        dom.appendChild(d);
                        d._isremove = false;
                        domReset(d);
                    },this);
                }
                i++;
            },this);
            while(i<len){
                dom.J4bind_children[i].each(function(n,sdom){
                    sdom.remove();
                    sdom._isremove = true;
                });
                i++;
            }                 
        }
        function refreshList(dom){
            var sname = dom.bindAttr['list'].data['a'];
            if(sname===undefined || sname === null || sname!==sname){
                console.error('不能读取到list值',dom.bindAttr['list']);
                return;
            }
            //dom.bindAttr['list_father'].data.a = sname;
            var value = this.Get(sname);     
            if(!value || typeof(value)!='object' || !dom.J4bind_tpl || (value.__type__!='indexArray' && value.__type__!='BindArray')){
                dom.J4bind_children.each(function(i,v){
                    v.each(function(n,sdom){
                        sdom.remove();
                        sdom._isremove = true;
                    });
                });
                return;
            }
            _refreshList.call(this,dom,value,sname);
        }
        //超大表格
        function refreshLargerList(dom){
            var sname = dom.bindAttr['largerlist'].data['a'];
            if(sname===undefined || sname === null || sname!==sname){
                console.error('不能读取到list值',dom.bindAttr['largerlist']);
                return;
            }    
            var value = this.Get(sname);     
            if(!value || typeof(value)!='object' || !dom.J4bind_tpl || (value.__type__!='indexArray' && value.__type__!='BindArray')){
                dom.J4bind_children.each(function(i,v){
                    v.each(function(n,sdom){
                        sdom.remove();
                        sdom._isremove = true;
                    });
                });
                return;
            }
            
        }
        
        function refreshWhile(dom,value){ 
            value = value || 0;   
            var i,len=dom.J4bind_children.length;    
            for(i=0;i<value;i++){
                if(i<len){
                    dom.J4bind_children[i].each(function(n,sdom){
                        this.InitDom(sdom);//子节点在父节点后面更新，属以初始化后不退出节点遍历，那后面遍历到时一定以及初始化
                        dataChange.call(this,sdom,i,i,false);
                        if(sdom._isremove){
                            dom.appendChild(sdom);
                            sdom._isremove = false;
                        }
                    },this);
                }else{
                    dom.J4bind_children[i] = [];
                    var tpl=dom.J4bind_tpl.cloneNode(true);
                    this.InitDom(tpl);
                    var a=[];
                    tpl.children.each(function(k,d){
                        a.push(d);
                    });
                    a.each(function(k,d){
                        dom.J4bind_children[i].push(d);
                        dataChange.call(this,d,i,i,false);
                        dom.appendChild(d);
                        d._isremove = false;
                    },this);
                }
            }
            while(i<len){
                dom.J4bind_children[i].each(function(n,sdom){
                    sdom.remove();
                    sdom._isremove = true;
                });
                i++;
            }
        }
                
        function _refreshDom(dom,attr,value){  
            if(attr.startsWith('class_')){
                value = (value===undefined || value===null)?"":(value===0?'0':value);
                if(!value){
                    return;
                }
                if(typeof(value)!='string'){
                    value = value.toString();
                }
                if(value.startsWith('add ')){
                    value = value.substr(4);
                    if(!dom.hasClass(value)){
                        dom.addClass(value);
                        this.setScroll(dom);
                    }
                }else if(value.startsWith('remove ')){
                    value = value.substr(7);
                    if(dom.hasClass(value)){
                        dom.removeClass(value);
                    }
                }
                return;
            }else if(attr.startsWith('class-')){
                value = (value===undefined || value===null)?"":(value===0?'0':value);
                var cn = attr.substr(6);
                //console.log(attr,dom);
                if(value){
                    if(!dom.hasClass(cn)){
                        dom.addClass(cn);
                        this.setScroll(dom);
                    }
                }else{
                    dom.removeClass(cn);
                }
                return;
            }else if(attr.startsWith("style-")){
                value = (value===undefined || value===null)?"":value;
                var cn = attr.substr(6);
                dom.style[cn]=value;
            }        
            switch(attr){
                case 'show':
                case '_if':
                    value = value || false;
                    if(value){
                        dom.removeClass('hidden');
                        dom.removeClass('hide');
                        dom.addClass('show');
                    }else{
                        dom.addClass('hidden');
                        dom.removeClass('show');
                    }
                    break;
                case 'hidden':
                case 'hide':
                    value = value || false;
                    //console.log('show',value);
                    if(!value){
                        dom.removeClass('hidden');
                        dom.removeClass('hide');
                        dom.addClass('show');
                    }else{
                        dom.addClass('hidden');
                        dom.removeClass('show');
                    }
                    break;
                case 'name':
                    value = (value===undefined || value===null)?"":(value===0?'0':value);
                    dom.setAttribute('name',value);
                    break;
                case 'data':
                    value = (value===undefined || value===null)?"":(value===0?'0':value);                    
                    dom.setAttribute('data',value);
                    break;
                case 'href':
                    if(value===undefined || value===null){
                        dom.removeAttribute('href');
                        break;
                    }
                    value = value===0?'0':value;
                    this.ReWiteUrl(value,'api');
                    dom.setAttribute('href',value);
                    break;
                case 'src':
                    if(value===undefined || value===null){
                         dom.removeAttribute('src');
                        break;
                    }
                    if(value)this.ReWiteUrl(value,'api');
                    dom.setAttribute('src',value);
                    break;  
                case 'src2':
                    if(value===undefined || value===null){
                        dom.removeAttribute('src');
                        break;
                    }
                    if(value.search(/(^http:\/\/)|(^https:\/\/)/i)==-1){
                        value = '/' + value.Trim("/ ");
                    }
                    dom.setAttribute('src',value);
                    break;  
                case 'img':
                    dom.innerHTML = '';
                    //console.log(value);
                    if(!value || typeof(value)!='object' || value.__type__ !== 'Image'){
                        break;    
                    }
                    dom.appendChild(value);
                    break;         
				case 'text':
                    value = (value===undefined || value===null)?"":(value===0?'0':value);
					dom.innerText=value;
                    dom._dt = true;
					break;
                case 'html'://没有做xss过滤，慎用
                    value = (value===undefined || value===null)?"":(value===0?'0':value);
                    dom.innerHTML= J4.FilterXss(value);
                    this.InitDom(dom,dom.bindsname);//,dom.bindfather);
                    dom._dt = true;
                    domReset(dom);
                    break;
				case 'value': //setVal扩展,优先使用该方法代替text和html
                    value = (value===undefined || value===null)?"":(value===0?'0':value);
                    if(dom.hasClass('J4-inputHtml')){//其他情况没有做xss过滤，慎用
                        //应该在这里做xss过滤
                        value = J4.FilterXss(value);
                    }
                    if(typeof(value)=="string"){
                        value = value.Trim();
                    }
                    dom.setVal(value);
                    dom.oldValue = value;
                    if(value && dom.nodeName == 'SELECT' && dom.getVal().value!=value){
                         console.error('对SELECT设置的值无效',value,dom.getVal().value,dom.cloneNode(true));
                    }
                    if(dom.nodeName != 'SELECT' && dom.nodeName != 'INPUT'){
                        dom._dt = true;
                    }
					break; 
                case 'disabled':
                    value = (value===undefined || value===null || value===false)?false:(value===0?false:true);
                    if(value){
                        dom.setAttribute('disabled','');
                    }else{
                        dom.removeAttribute('disabled');
                    }
                    break;
                case 'edit':
                    value = (value===undefined || value===null || value===false)?false:(value===0?false:true);
                    dom.__isedit = value;
                    if(value){
                        dom.setAttribute('contenteditable','true');
                    }else{
                        dom.removeAttribute('contenteditable');
                    }
                    break;
                case 'id':
                    value = (value===undefined || value===null)?"":(value===0?'0':value);     
                    if(typeof(value)=="string"){
                        value = value.Trim();
                    }
					dom.setAttribute('id',value);
                    break;
                case 'placeholder':
                    value = (value===undefined || value===null)?"":(value===0?'0':value);
                    if(typeof(value)=="string"){
                        value = value.Trim();
                    }
					dom.setAttribute('placeholder',value);
                    break;
                case 'del':
                    value = exp.call(this,data) || false;
                    if(value && typeof(value)=='object' && (value.__type__=='indexArray' || value.__type__=='BindArray')){
                        //value.del(data[id]);
                    }
                    break;     
                case 'inputCheck':  
                case 'tpl':
                case 'list':
                case 'list_father':
                case 'list_if':
                case 'list_orderBy':
                case 'input':
                case 'clickinput':
                case 'errorinput':
                case 'print':
                case 'printlist_if':
                    break;               
				default: 
                    //console.log('未定义的绑定属性:'+attr);
                    dom.setAttribute(attr,value);
					break;    
            }        
        }
        
        function refreshDom2(dom,counter,counterAll,__id){
            //console.error(dom.outerHTML);
            var rs = true;
            if(!dom.bindAttr){
                return;
            }
            if(dom.bindAttr['textList']){
                var text ='';
                dom.bindAttr['textList'].each(function(i,v){
                    if(v &&v.__type__=='String'){
                        text+=v;
                    }else if(v && typeof(v)=='object'){
                        text+=this.readData(dom,v,counter,counterAll,__id);    
                    }
                },this);
                //console.log(text,dom.bindAttr['textList']);
                dom.innerText = text;
                //dom.textContent = text;
                //return false;
            }
            var Highlight=false;
            var Highlight_txt=false;
            if(dom.bindAttr["print"]){
                var data = J4.CopyObj(dom.bindAttr["print"].data);
                var bind = {}
                data.each(function(i,v){
                    if(v.startsWith('../')){
                        v = _readData.call(this,dom,v);
                    }
                    if(v.endsWith("counter")){
                        data[i] = counter;
                    }else{
                        data[i]=this.Get(v);
                    }
                    bind[i]=v;
                },this); 
                data.__id = __id;
                data.counter = counter;
                data.counterAll = counterAll;
                console.log({
                    'Calc':dom.bindAttr["print"].exp.srcCode,
                    'bind':bind,
                    'data':J4.CopyObj(data),
                    'value':J4.CopyObj(this.readData(dom,dom.bindAttr["print"],counter,counterAll,__id)),
                    'dom':dom,
                    '_this':this});
            } 
            dom.bindAttr.each(function(attr,CalcObj){ 
                if(attr=='textList'){
                    return;
                }else if(attr.startsWith("list")||attr.startsWith('print')){
                    return;
                }else if(attr.startsWith("highlight-") || attr.startsWith("highlight_")){//高亮特定字符
                    var value = this.readData(dom,CalcObj,counter,counterAll,__id);    
                    value = (value===undefined || value===null)?false:(value===0?'0':value);                   
                    Highlight = attr.substr(10);
                    Highlight_txt = value;
                }else if(attr=='value' && dom.nodeName=='SELECT' && dom.bindAttr['list']){
                    return;
                }else{
                    var value = this.readData(dom,CalcObj,counter,counterAll,__id);    
                    _refreshDom.call(this,dom,attr,value);
                }
            },this);
            if(dom.bindAttr['_if']){
                var value = this.readData(dom,dom.bindAttr['_if'],counter,counterAll,__id);
                if(!value){
                   return false;
                }
                if(value!=dom.J4ifvalue){ 
                   dom.J4ifvalue = value;
                   dom.eachChildren(function(dom2){
                       if(dom2.modbox){
                           return false;
                       }
                       if(!dom2.bindAttr){
                           return;
                       }
                       if(refreshDom.call(this,dom2,counter,counterAll,__id)===false){
                           return false;    
                       }              
                   },this);
                   return false;
                }
            }        
            if(Highlight_txt && dom._dt){
                dom._dt = false;
                var reg = new RegExp("(" + Highlight_txt + ")", "ig");  
                dom.innerHTML = dom.innerHTML.replace(reg, '<span class="highlight '+Highlight+'">$1</span>');
            }
            if(dom.bindAttr['list']){
                 if(dom.unLoopList){
                     dom.unLoopList.each(function(i,v){
                         //console.log(v);
                         dataChange.call(this,v,counter,counterAll,__id);
                     },this);
                 }
                 refreshList.call(this,dom);
                 if(dom.nodeName=='SELECT' && dom.bindAttr['value']){
                     var value = this.readData(dom,dom.bindAttr['value'],counter,counterAll,__id); 
                     //_refreshDom.call(this,dom,'value',value);
                     dom.setVal(value);
                     if(value && dom.getVal().value!=value){
                         console.error('对SELECT设置的值无效',value,dom.getVal().value,dom.cloneNode(true));
                     }
                 }
                 return false;
            }else if(dom.bindAttr['largerlist']){
                refreshLargerList.call(this,dom);
                return false;
            }else if(dom.bindAttr['_while']){
                 var value = this.readData(dom,dom.bindAttr['_while'],counter,counterAll,__id);
                 refreshWhile.call(this,dom);
                 return false;
            }
        }
        function refreshDom(dom,counter,counterAll,__id){
            var a = refreshDom2.call(this,dom,counter,counterAll,__id);
            if(typeof(dom.onrefresh)=="function"){
                dom.onrefresh({
                    type:'refresh',
                    target:dom,
                    srcElement:dom,
                    eachNode:function(className,fn,_this){
                        dom.eachFather(className,fn,_this);
                    },
                });
            }
            return a;
        }
        function testBind(dom,clist){ //检查dom是否需要更新
            return clist.each(function(i,v){    
                return dom.J4bind_datalist.each(function(bname){  
                    if(bname.startsWith(v)){
                        return false;
                    }
                });
            });
        }
        function dataChange(dom,counter,counterAll,__id){ //找出需要更新的dom进行更新
            var nameList = this.isChangeList;
            //console.error("DataChange",nameList,dom.outerHTML);
            if(!nameList){
                return;
            }
            if(!dom){
                //dom = this.dom;
            }
            if(dom.bindAttr){   
                if(testBind(dom,nameList)===false && refreshDom.call(this,dom,counter,counterAll,__id)===false){
                    return;    
                }              
            }                       
            dom.eachChildren(function(dom2){
                if(dom2.modbox){
                    return false;
                }
                if(!dom2.bindAttr){
                    return;
                }
                if(testBind(dom2,nameList)===false && refreshDom.call(this,dom2,counter,counterAll,__id)===false){
                    return false;    
                }              
            },this);
        }
        var isChangeList = false;//表示当前没有更新
        return function(name){
            //console.error("DataChange",name);
            if(!name || typeof(name)!='string'){
                console.error(name);
                return;
            }
            if(this._notActive){
                return;
            }
            if(!isChangeList){
                isChangeList = {};
                setTimeout(function(){
                    isChangeList.each(function(i,v){
                        if(v.cfgObj && v.cfgObj.beforeUpdate){
                            v.cfgObj.beforeUpdate.call(v);
                        }
                        if(v.dom)dataChange.call(v,v.dom);
                        v.subDom.each(function(k,d){
                            dataChange.call(v,d);
                        });
                        if(v.cfgObj && v.cfgObj.updated){
                            v.cfgObj.updated.call(v);
                        }
                    });
                    isChangeList = false;
                },20);
            }
            
            name = '/'+name.Trim('/');
            var t = this.isChangeList.each(function(i,v){
                if(name.startsWith(v)){
                    return false;
                }else if(v.startsWith(name)){
                    this.isChangeList[i] =  name;
                    return false;
                }
            },this);
            if(t!==false){
                this.isChangeList.push(name);
            }
            var id = this.oid;//this.view?this.view.id:this.id;
            if(!isChangeList[id]){//第一步先将需要更新的值记录下来
                isChangeList[id] = this;
            }
        }
        
    })(),
    Input:function(ib,value,obj){
        var exp = ib.exp;
        var data = {};
        ib.data.each(function(i,v){
            data[i]=this.Get(v);
        },this);          
        var oldValue,rb; 
        if(exp.exp=='a' && !data['saveTo']){
            oldValue = data['a'];
            rb = ib.data['a'];
        }else{
            oldValue = data['saveTo'];  
            rb = ib.data['saveTo'];
            data['value'] = value;
            value = exp.call(this,data);
        }
        if(typeof(value)=='string'){
            value = J4.FilterXss(value).Trim();
        }
        if(!rb){
            return;
        }
        if(obj && obj.type=="checkList"){
            var last = this.Get(rb);
            var name = obj.dom.getAttribute("name");
            if(name){
                if(!last){
                    last={};
                }
                if(obj.dom.checked){
                    last[name]=value;
                }else{
                    last.del(name);
                }
            }else{
                if(!last){
                    last=[];
                }
                var sv = true;
                last.each(function(i,v){
                    if(v==value){
                        if(!obj.dom.checked){
                            last.del(i);
                        }
                        sv = false;
                        return false;
                    }
                });
                if(sv && obj.dom.checked){
                    last.push(value);
                }
            }
            this.Set(rb,last);
        }else{
            if(value==oldValue){
                return;
            }
            this.Set(rb,value);
        }
    },
    DataInput:function(sdom,value,obj){
        if(!sdom.bindAttr || !sdom.bindAttr['input']){
            return;
        }
        if(obj){
            obj.dom = sdom;
        }
        this.Input(sdom.bindAttr['input'],value,obj);
    },
    ClickInput:function(sdom){
        if(!sdom.bindAttr || !sdom.bindAttr['clickinput']){
            return;
        }
        var ib = sdom.bindAttr['clickinput'];
        if(!ib.data['saveTo_0']){
            this.Input(ib,'click'); 
            return;
        }
        var exp = ib.exp;
        var data = {};
        ib.data.each(function(i,v){
            if(i.startsWith('saveTo_')){
                return;
            }
            data[i.substr(1)]=this.Get(v);
        },this);   
        data.each(function(i,value){
            var name = 'saveTo'+i;
            if(!ib.data[name]){
                return;
            }
            this.Set(ib.data[name],value);
        },this);
    },
    ErrorInput:function(sdom,error){
        //console.log(error);
        if(!sdom.bindAttr || !sdom.bindAttr['errorinput']){
            return;
        }
        this.Input(sdom.bindAttr['errorinput'],error);                 
    },
    appendTo:function(boxid){
        if(typeof(boxid)=='string'){
            if(boxid=='J4-floatwindow'|| boxid=='window'){
                this.dom.boxid = 'window';
            }else{
                domReset(this.dom);
                boxid = this.dom.appendTo(boxid);
                if(!boxid.id){
                    boxid.id = J4.GetOnlyId();
                }
                this.dom.boxid = boxid.id;
            }
        }else if(typeof(boxid)=='object'){
            if(boxid.__type__=='Node'){
                if(!boxid.id){
                    boxid.id = J4.GetOnlyId();
                }
                //J4.event('domReset').run(this.dom);
                domReset(this.dom);
                boxid.appendChild(this.dom);
                this.dom.boxid = boxid.id;
            }else{
                console.error('视图初始化失败');
            }
        }
        if(this.cfgObj && this.cfgObj.mounted){
            this.cfgObj.mounted.call(this,this.dom);
        }
    },
    subDomAppendTo:function(name,boxid){
        if(!this.subDom[name]){
            return;
        }
        if(typeof(boxid)=='string'){
            if(boxid=='J4-floatwindow'|| boxid=='window'){
                //J4.event('domReset').run(this.subDom[name]);
                this.subDom[name].boxid = 'window';
            }else{
                //J4.event('domReset').run(this.subDom[name]);
                domReset(this.subDom[name]);
                boxid = this.subDom[name].appendTo(boxid);
                if(!boxid.id){
                    boxid.id = J4.GetOnlyId();
                }
                this.subDom[name].boxid = boxid.id;
            }
        }else if(typeof(boxid)=='object'){
            if(boxid.__type__=='Node'){
                if(!boxid.id){
                    boxid.id = J4.GetOnlyId();
                }
                //J4.event('domReset').run(this.subDom[name]);
                domReset(this.subDom[name]);
                boxid.appendChild(this.subDom[name]);
                this.subDom[name].boxid = boxid.id;
            }else{
                console.error('视图初始化失败');
            }
        }
        if(this.cfgObj && this.cfgObj.mounted){
            this.cfgObj.mounted.call(this,this.dom.subDom[name]);
        }
    },
    show:function(name){
        if(this._notActive){
            this._notActive = false;
            this.DataChange('/');  
            this._notActive = true;
        }
        var dom = this.dom;
        if(name){
            dom  = this.subDom[name];
        }else if(this.router && this.router.auto){
            this.router.Enable();
        }
        if(!dom){
            return this;
        }
        if(this.cfgObj && this.cfgObj.beforShow){
            if(this.cfgObj.beforShow.call(this,dom,name)===false){
                return this;
            }
        }
        if(dom.boxid=='window'){
            if(dom.win){
                dom.win.show();
                return this;
            }else{
                console.error('dom无法显示');
            }
        }
        //J4.event('domReset').run(dom);
        if(dom.hasClass('hidden')){
            dom.removeClass('hidden');
        }
        dom.addClass('show');       
        return this;
    },
    hide:function(name){
        var dom = this.dom;
        if(name){
            dom  = this.subDom[name];
        }else if(this.router && this.router.auto){
            this.router.Disable();
        }
        if(!dom){
            return;
        }
        this.setTimeout(function(){
        if(this.cfgObj && this.cfgObj.beforHide){
            if(this.cfgObj.beforHide.call(this,dom,name)===false){
                return;
            }
        }
        if(dom.boxid=='window'){
            if(dom.win){
                dom.win.remove();
                return this;
            }else{
                console.error('window移除错误');
            }
        }
        if(!dom.hasClass('hidden')){
            dom.addClass('hidden');
        }
        dom.removeClass('show');
        },25);
        return this;
    },
    remove:function(name){
        if(name){
            this.hide(name);
            delete(this.subDom[name]);
        }else{
            this.hide();
        }
        this.setTimeout(function(){
        if(this.cfgObj.beforeDestroy){
            this.cfgObj.beforeDestroy.call(this);
        }
        if(this.detaSet){
            this.detaSet.removeCallBack(this.oid);
        }
        this.dom.remove();
        if(this.cfgObj.style){
            this.cfgObj.style.each(function(i,v){
                v.remove();
            });
        }
        if(this.cfgObj.destroyed){
            this.cfgObj.destroyed.call(this);
        }
        },35);
        return this;
    },
    setScroll:function(dom){
        if(!dom.hasClass('sel,select')){
            return;
        }    
        return;
        dom.FilterFatherClass("setScroll","J4-view",function(fdom){
            //fdom.getAttribute("setScroll");
            if(fdom.J4_donotScroll){
                fdom.J4_donotScroll = false;
                return;
            }
            //console.log(dom.offsetTop,fdom.offsetHeight); 
            var dom_offsetTop = dom.offsetTop;
            var dom_offsetHeight = dom.offsetHeight;
            var fdom_offsetHeight = fdom.offsetHeight;
            var fdom_scrollTop = fdom.scrollTop;
            if(dom_offsetTop+dom_offsetHeight+100>fdom_offsetHeight+fdom_scrollTop){
                fdom_scrollTop = dom_offsetTop+dom_offsetHeight+100-fdom_offsetHeight;
                if(fdom_scrollTop<0){
                    return false;
                }
                if(fdom_scrollTop>fdom.scrollHeight){
                    fdom.scrollTop=fdom.scrollHeight;
                }else{
                    fdom.scrollTop=fdom_scrollTop;
                }
            }else if(dom_offsetTop-100<fdom_scrollTop){
                fdom_scrollTop = dom_offsetTop-100;
                if(fdom_scrollTop>=0){
                    fdom.scrollTop=fdom_scrollTop;
                }else{
                    fdom.scrollTop=0;
                }
            }
            return false;
        });
          
    },
    FullWindow:function(name){
        var dom = this.dom;
        if(name){
            dom  = this.subDom[name];
        }
        if(!dom){
            return this;
        }
        J4.FullWindow(dom);
        return this;
    },
    runEvent:function(ename,argu){
        
        return rs;
    },
    getCanvas:function(name){
        var cxt;
        this.dom.getElementsByTagName('canvas').each(function(i,dom){
            if(dom.getAttribute('name')==name){
                cxt = dom.getContext("2d");     
                cxt.resetWH = function(w,h){
                    var dom = this.canvas;
                    var father = dom.parentNode || dom.parentElement; 
                    dom.width=w?w:father.offsetWidth;
                    dom.height=h?h:father.offsetHeight;  
                    this.width = dom.width; 
                    this.height = dom.height;
                    if(this.width==0 || this.height==0){
                        return null;
                    }
                    return this;
                }
                cxt.resetWH();                         
                return false;
            }
        },this);
        return cxt;  
    },
    create:function(sel,ishide){
        if(ishide){
            this.hide();
        }else if(ishide===false){
            this.show();
        }
        if(sel){
            this.appendTo(sel);
        }       
        return this;
    },
}
Object.setPrototypeOf(Dom.prototype , J4Module);  
J4.Dom = function(html,dataSet){
    return new Dom(html,dataSet);
}

//定义外部调用接口
window.J4  = (function(){
    function createRouter(){        
        var mod = this.cfgObj;
        if(!mod.router){
            return;
        }
        this.router = J4.CreateRouter(this,mod.routerName);
        mod.router.each(function(i,v){
            if(!v){
                return;
            }
            if(typeof(v)=='string'){
                v = this[v];
            }
            if(typeof(v)!='function'){
                console.error('路由绑定错误：'+i,v);
            }
            this.router.Add(i,v);
        },this);
    }
    function _onload(objlist){
        this._onload = null;
        this.modules = objlist;
        if(this.onload && typeof(this.onload)=='function'){
            this.onload();
        }
        this.onload = null;
    }
    function _onload2(objlist){
        this.cfgObj._onload(objlist);
        delete(this._onload);
        var mod = this.cfgObj;        
        if(objlist && objlist.__type__=='Object'){
            objlist.each(function(i,v){
                if(!v || v===true){
                    return;
                }
                if(v.__type__=='J4Dom'){
                    this[i]=v;
                }
            },this);
        }
        if(mod.dom){
            this.SetHtml(mod.dom.cloneNode(true));
        }
        if(mod.subDom){
            mod.subDom.each(function(i,v){
                if(v.__type__=='Node'){
                    v = v.cloneNode(true);
                }
                this.SetHtml(i,v);
            },this);
        }
        if(mod.oninit){
            mod.oninit.call(this);
        }
        //initRouter.call(this);
    }
    function create(sel,ishide){
        if(this.Dom){
            //return this.Dom;
        }
        var mod = J4.Dom();
        mod.name = this.name;
        if(this.srcPath){
            mod.srcPath = this.srcPath.Trim('/')+'/';
        }
        if(this.apiPath){
            mod.apiPath = this.apiPath.Trim('/')+'/';
        }
        mod.cfgObj = this;
        mod.modules = this.modules;
        mod.computed = this.computed;
        if(this.methods){
            mod.Extend(this.methods);
        }
        if(this.data){
            mod.SetData(this.data);
        }
        createRouter.call(mod);
        if(this.created){
            this.created.call(mod);
        }
        if(!this._onload){
            if(this.modules && this.modules.__type__=='Object'){
                this.modules.each(function(i,v){
                    if(!v || v===true){
                        return;
                    }
                    if(v.__type__=='J4Dom'){//||v.__type__=='Module'
                        mod[i]=v;
                    }
                },mod);
            }
            if(this.dom){
                mod.SetHtml(this.dom.cloneNode(true));
            }
            if(this.subDom){
                this.subDom.each(function(i,v){
                    if(v.__type__=='Node'){
                        v = v.cloneNode(true);
                    }
                    mod.SetHtml(i,v);
                });
            }
            mod.create(sel,ishide);
            if(this.oninit){
                this.oninit.call(mod);
            }
            //initRouter.call(this);
        }else{
            J4Module.loaddingModule = mod;
            mod._onload = _onload2;
        }
        return mod;
    }
    return function(obj,methods){
        if(typeof(fn)=='function'){
            J4Module.loaddingModule = fn();
            return obj;
        }
        obj.__type__='Module';
        if(methods){
            obj.methods = methods;
        }
        obj._onload = _onload;
        obj.create = create;
        Object.setPrototypeOf(obj , J4Module);  
        J4Module.loaddingModule = obj;
        return obj;
    }
})();
Object.setPrototypeOf(window.J4 , J4);  
//window.J4.prototype = J4;

//向页面添加必要的html节点，包括弹窗、遮罩层等
function initHtml(){
    var body=document.getElementsByTagName('body')[0];
    //设置模态框和遮罩层的位置
    var html =
        '<div id="J4-loadding" class="hidden" style="background:rgba(50 ,50,50, 0.3)">'+
            '<div id="J4-loadding-img" style="position:absolute;left:50%;top:30%;transform:translate(-50%, -30%);">'+
                '<img src="'+J4.CFG.LoaddingIMGURL+'" style="width:80px;">'+
            '</div>'
            '<div id="J4-loadding-progress" style="position:absolute;left:50%;top:30%;transform:translate(-50%, 0);'+
                'width:80%;max-width:300px;padding-top:80px;"></div>'+
        '</div>';    
    body.append2(html);     
    html = 
        '<div id="J4-floatwindow"  class="modalwindow hidden">'+
            '<div id="J4-floatwindow-opacity" class="opacity"></div>'+
        '</div>';
    J4.floatwindow  = body.append2(html); 
}

//加载中遮罩层显示
(function(){
    /*这个方法显示一个遮罩层，避免用户重复点击或在不允许对页面做任何操作期间进行操作*/
    //startLoadding()stopLoadding()表示结束。调用多少次start就必须多少次stop 
    var ajaxCount=0;
    function startLoadding(){
        if(ajaxCount==0){
            document.getElementById('J4-loadding').removeClass('hidden');
        }
        ajaxCount++;
    }
    function stopLoadding(){
        ajaxCount--;
        if(ajaxCount==0){
            var _this = this;
            //让其他后续内容处理完后再关闭
            setTimeout(function(){
                if(ajaxCount==0){
                    document.getElementById('J4-loadding').addClass('hidden');
                }
            },500);
        }
    }
    J4Module.startLoadding = startLoadding;
    J4Module.stopLoadding = stopLoadding;
    J4.startLoadding = startLoadding;
    J4.stopLoadding = stopLoadding;
})(); 
//创建弹窗对象
J4Module.win = (function(){      
    //header处理
    function initHeader(header){
        if(!header || header.__type__=='String'){
            var a = '<h3><span class="title">'+(header?header:'窗口')+'</span></h3>';
            header = document.createElement("div");
            header.innerHTML = a;
            var c = document.createElement("a");
            c.innerHTML = '<i class="J4-icon-close"></i>';
            c.addClass('J4-btn J4-win-close');
            c.btnname = 'close';
            header.appendChild(c);
        }else if(header.__type__=='Node'){
            header.remove();
        }else{
            console.error('创建对话框参数出错');
            return;
        }
        header.addClass('J4-win-header');
        return header;
    }
    //footer处理
    function initFooter(footer){
        if(footer && footer.__type__=='String'){
            footer = document.createElement("div");
            footer.innerHTML = footer;
        }else if(footer && footer.__type__=='Node'){
            footer.remove();
        }else if(!footer){
            var dom = document.createElement("div");  
            var btnlist = {close:{name:'close',text:"关闭"}};
            dom.appendChild(CreateBtn('close','关闭'));
        }else if(footer.__type__=='Object'||footer.__type__=='Array'){
            var dom = document.createElement("div");  
            //var btnlist = {};
            footer.each(function(i,v){
                if(!v.text){
                    console.error('创建窗口按钮失败：'+v);
                }
                if(!v.name){
                    v.name = J4.GetOnlyId();
                }
                //btnlist[v.name]=v;
                dom.appendChild(CreateBtn(v.name,v.text,v.type));
            });
            footer = dom;
        }else{
            console.error('创建对话框参数出错');
            return;
        }
        footer.addClass('J4-win-footer');
        return footer;
    }
    //添加下面按钮    
    function CreateBtn(name,text,type){
        var btn = document.createElement("button");  
        btn.addClass('J4-btn');
        btn.innerText =  text;
        //btn.setAttribute('name',name);
        btn.btnname = name;
        if(type!==false){
            btn.addClass('J4-btn-primary');
        }           
        return btn;
    }
    //按钮事件代理和分发
    function btnClick(e){
        var box,dom,name,rs; 
        e.eachNode(function(btn){
            if(btn.btnname){
                dom = btn;
            }else if(btn.hasClass('J4-win-close')){
                dom = btn;
                dom.btnname = 'close';
            }
            if(btn.hasClass('J4-window')){
                box=btn;
                return false;
            }
        });
        if(!dom){
            return;
        }
        name = dom.btnname;   
        if(box.win.btnlist[name] && typeof(box.win.btnlist[name].callback)=='function'){
            var _this = box.win.btnThis;
            if(box.win.btnlist[name].callback.call(_this?_this:box,name)===false){
                if(e.preventDefault){
                    e.preventDefault();
                    e.stopPropagation();
                }
                return false;
            }
        }
        if(name == 'close'){
            box.win.remove();
        }
    }
    //content处理
    function initContent(content){
        if(!content || content.__type__=='String'){
            var dom = document.createElement("div");
            dom.innerHTML = content; 
            content = dom;
        }else if(content.__type__=='Node'){
            content.remove();
        }else{
            console.error('创建对话框参数出错');
            return;
        }
        //content.setAttribute('style','max-height:80%;')
        if(!content.getAttribute('resize')){
            content.setAttribute('resize','max-height:height-150;');
        }
        content.addClass('J4-win-content J4-resize');
        return content;
    }
    
    function createWindow(html){
        if(!html){
            html = {};
        }
        if(typeof(html)!='object' && typeof(html)!='string'){
            console.error('创建对话框参数出错');
            return;
        }     
        if(html.__type__ == 'String'){
            html = document.createElement("div").resetChildren(html);  
        }    
        var header,content,footer;    
        //获取传入的节点模块
        if(html.__type__ == 'Node'){
            header = html.getElementsByClassName('J4-win-header')[0];
            content = html.getElementsByClassName('J4-win-content')[0];
            footer = html.getElementsByClassName('J4-win-footer')[0];
        }else{
            header = html.header;
            content = html.content;
            footer = html.footer;
        }
        //header处理
        header = initHeader(header);
        content = initContent(content);
        footer = initFooter(footer);
        
        //最终的dom节点
        var dom = document.createElement("div");
        dom.addClass('J4-floatwindow');
        dom.appendChild(header);
        dom.appendChild(content);
        dom.appendChild(footer);            
        dom.header = header;
        dom.content =content;
        dom.footer = footer;        
        return dom;
    }
    
    function winobj(title,content,footer){
        if(!content){
            this.header = initHeader('提示消息');    
            this.content = initContent(title);
        }else if(title && title.__type__=='Object'){
            if(!title.content){
                console.error('创建弹窗失败：错误的参数');
                return;
            }
            if(this.title){
                this.header = initHeader(title.title);
            }else{
                this.header = initHeader('提示消息');  
            }
            this.content = initHeader(title.content);
            if(title.footer){
                this.footer = initFooter(title.footer);
            }
        }else{
            this.header = initHeader(title);
            this.content = initContent(content);
        }
        this.btnlist = {};
        if(footer && typeof(footer)=='object'){
            footer.each(function(i,v){
                if(!v.name){
                    v.name = J4.GetOnlyId();
                }
                this.btnlist[v.name]=v;    
            },this);
        }
        if(footer){
            this.footer = initFooter(footer);
        }
        this.btnThis = this;
        this.dom=null;
    }
    winobj.prototype = {  
        init:function(){
            if(!this.dom){
                var dom = document.createElement("div");
                dom.addClass('J4-window');
                dom.appendChild(this.header);
                dom.appendChild(this.content);
                if(!this.footer){
                    if(this.btnlist.isEmpty()){
                       this.btnlist['close']={name:'close',text:'关闭'}; 
                    }
                    this.footer = initFooter(this.btnlist);
                }
                dom.appendChild(this.footer); 
                dom.win = this;
                this.header.onclick = btnClick;
                this.footer.onclick = btnClick;
                //dom.onclick = btnClick;
                this.dom = dom;
                //J4.event('domReset').run(this.dom);
                domReset(this.dom);
            }
            return this.dom;
        },
        //name和type可以省略,传参方式有
        // (text,type,callBack)  (text,callBack) (options:{name,text,type,callback})
        addButton:function(text,type,callback){ 
            if(arguments.length<2){
                console.error('创建窗口回调函数参数缺失');
                return;
            }
            //省略type参数处理
            if(typeof(type)=='function'){
                callback =  type;
                type = undefined;
            }
            var name;
            if(typeof(text)=='object'){
                name = text.name;
                type = text.type;
                callback = text.callback;
                text = text.text;
            }
            if(!name){
                name = J4.GetOnlyId();
            }
            this.btnlist[name]={name:name,text:text,callback:callback,type:type};
            if(this.footer){
                var btn = CreateBtn(name,text,type);
                J4.event('domReset').run(btn);
                this.footer.appendChild(btn);
            }
            return this;
        },
        show:function(){
            this.init();
            this.dom.show()
            this.dom.appendTo(J4.floatwindow);
            if(J4.floatwindow.children.length==2){
                J4.floatwindow.show();
            }
            return this;
        },
        hide:function(){
            if(J4.floatwindow.children.length==2){
                J4.floatwindow.hide();
            }
            this.dom.hide();  
            this.dom.remove();
            return this;
        },
        remove:function(){
            if(J4.floatwindow.children.length==2){
                J4.floatwindow.hide();
            }
            this.dom.hide();
            this.dom.remove();
            return this;
        },
        addClass:function(c){
            this.dom.addClass(c);
            return this;
        },
        createMod:function(dataSet){
            this.init();
            var dom = J4.Dom(this.dom,dataSet); 
            this.btnThis = dom;
            return dom;
        },
    }
    //title,content,footer既可以是字符串也可以是dom节点
    return function(title,content,footer){
        var win = new winobj(title,content,footer); 
        win.btnThis = this;
        return win;
    }
})(),
J4.win = J4Module.win;
J4.Msg  = function(title,msg,btn){
    var obj = J4.win(title,msg,btn);
    obj.show();
    obj.addClass('msgwin');
    return obj;
}
J4Module.Msg = function(title,msg,btn){
    var obj = J4.win(title,msg,btn);
    obj.show();
    obj.addClass('msgwin');
    return obj;
}
//页面大小变化后处理
var winsize={}
function Resize(){
    var body = document.getElementsByTagName('body')[0];
    //计算窗口高度
    var div=document.createElement('div');
    div.style.width="100%";
    div.style.height="100%";
    div.style.top="0px";
    div.style.right="0px";
    div.style.bottom="0px";
    div.style.left="0px";
    div.style.position='fixed';
    body.appendChild(div);
    winsize.width=div.offsetWidth;
    winsize.height=div.offsetHeight;
    div.remove();
    //J4.event('domReset').run(body);
    J4.Resize(body);
}
J4.Resize = function(rdom){
    rdom.getElementsByClassName('J4-resize').each(function(i,dom){
        var resize=dom.getAttribute('resize');
        if(!resize){
            return;
        }
        resize=resize.Trim();
        if(!resize){
            return;
        }
        resize.split(';').each(function(k,v){
            if(!v){
                return;
            }
            var n=v.indexOf(':');
            v=[v.substr(0,n),v.substr(n+1)];
            v[0]=v[0].Trim();
            v[1]=v[1].Trim();
            if(!v[0] || !v[1]){
                return false;
            }
            switch(v[0]){
                case 'max-height':
                    var d=J4.Calc(v[1],winsize);
                    dom.style.maxHeight=d+'px';
                    break;
                case 'max-width':
                    var d=J4.Calc(v[1],winsize);
                    dom.style.maxWidth=d+'px';
                    break;
                case 'min-height':
                    var d=J4.Calc(v[1],winsize);
                    dom.style.minHeight=d+'px';
                    break;
                case 'min-width':
                    var d=J4.Calc(v[1],winsize);
                    dom.style.minWidth=d+'px';
                    break;
                case 'height':
                    var d=J4.Calc(v[1],winsize);
                    dom.style.height=d+'px';
                    break;
                case 'width':
                    var d=J4.Calc(v[1],winsize);
                    dom.style.width=d+'px';
                    break;    
            }           
        });
    });       
};

//事件驱动型插件
(function(){
    var _plugins = {};
    function initPlug(dom){
        if(dom.nodeType==3){
            return;
        }        
        var plugList = {};
        var removelist = [];       
        dom.attributes.each(function(i,v){
            var name = v.name;
            var value = v.value.Trim(' ;');
            if(name.startsWith('j4plug-')){
                removelist.push(name);                                 
                name = name.substr(7);
                plugList[name] = value;
            }
        });
        removelist.each(function(i,v){
            dom.removeAttribute(v); 
        });
        //插件绑定
        var plugins = {};
        plugList.each(function(i,d){
            var argu = [];
            if(d){
                d = d.split(',');
                d.each(function(n,m){
                    if(!m){
                        return;
                    }
                    argu.push(m);                           
                });  
            }                
            plugins[i] = argu;
        });
        if(!plugins.isEmpty()){
            dom.plugins = plugins;
        }
    }
    function plugRun(e,type){
        if(e.plugRun){
            //e.plugRun = false;
            return;
        }
        e.plugRun = true;
        var ename = type?type:e.type;
        var rs;
        var lastDom = null;
        J4.event(ename).run(e,ename);
        if(ename=='hashchange'){
            var hash = decodeURI(location.hash.slice(1) || '/');
            var rs;
            _plugins.each(function(pname,plug){
                if(plug['hashchange']){
                    rs = plug['hashchange'](hash,e)===false?false:rs;
                }
            });
        }else if(ename=='domInit'){
            var domlist = [];
            if(!e.target.plugins){
                initPlug(e.target);
            }
            if(e.target.plugins){
                domlist.push(e.target);
            }
            e.target.eachChildren(function(dom){
                if(!dom.plugins){
                    initPlug(dom);
                }
                if(dom.plugins){
                    domlist.push(dom);
                }
            });
            domlist.each(function(i,dom){
                dom.plugins.each(function(pname,argu){
                    if(_plugins[pname]['domInit']){
                        argu = getArgu(e,argu,dom);
                        argu.push(dom);
                        argu.push(e);
                        rs = _plugins[pname]['domInit'].apply(_plugins[pname]['domInit'],argu)===false?false:rs;
                    }
                });
            });
        }else{
            e.eachNode(function(dom){     
                if(!dom.plugins){
                    lastDom = dom;
                    return;
                }
                dom.plugins.each(function(pname,argu){
                    if(_plugins[pname][ename]){
                        argu = getArgu(e,argu,dom,lastDom);
                        argu.push(dom);
                        argu.push(e);
                        var rs=_plugins[pname][ename].apply(_plugins[pname],argu)===false?false:rs;
                    }   
                });
                lastDom = dom;
            });
        }
        if(rs===false && e.preventDefault){
            e.preventDefault();
            e.stopPropagation();
        }
        return rs;
    };
    function getArgu(e,_argu,dom,lastDom){
        var argu = [];
        var value = e.__value;
        _argu.each(function(i,v){
            if(v==='event'){
                argu[i] = e;
                return;
            }else if(v==='this'||v==='self'){
                argu[i]=dom;
                return;
            }else if(v==='value'){
                if(value===undefined){
                    value = dom.getVal();
                }
                argu[i]=value.value;
                return;
            }else if(v==='valueinfo'){
                if(value===undefined){
                    value = dom.getVal();
                }
                argu[i]=value;
                return;
            }else if(v==='error'){
                if(value===undefined){
                    value = dom.getVal();
                }
                argu[i]=value.err;
                return;
            }else if(v==='child'){
                argu[i]=lastDom;
                return;
            }else if(v==='father'){
                argu[i]=dom.faterDom;
                return;
            }else if(v==='true'){
                argu[i]=true;
                return;
            }else if(v==='false'){
                argu[i]=false;
                return;
            }else if(v==='null'){
                argu[i]=null;
                return;
            }else if(v.startsWith("'")&& v.endsWith("'")){
                argu[i] = v.substr(1,v.length-2);
                return;
            }else if(v.startsWith('"')&& v.endsWith('"')){
                argu[i] = v.substr(1,v.length-2);
                return;
            }else if(!isNaN(v)){
                argu[i] = v*1;
                return;
            }else{
                //console.error('无法识别的参数：'+v);
                argu[i] = v;
            }
        }); 
        e.__value = value;
        return argu;
    }
    J4.Plugins = function(plugList){
        plugList.each(function(name,plug){
            if(_plugins[name]){
                console.error('同名插件被覆盖：'+name);
            }
            _plugins[name]=plug;
        });
        J4Module.loaddingModule = 'Plugins';
    }
    J4.PlugRun = plugRun;
    J4.PlugInit = initPlug;
    J4.ready(function(){
        var body=document.getElementsByTagName('body')[0];
        body.addEventListener('click',plugRun);//单击
        body.addEventListener('contextmenu',plugRun);//右键单击
        body.addEventListener('input',plugRun);//
        body.addEventListener('change',plugRun);//
        body.addEventListener('focusin',plugRun);//
        body.addEventListener('focusout',plugRun);//
        body.addEventListener('paste',plugRun);//
        body.addEventListener('dragover',plugRun);  
        body.addEventListener('drop',plugRun);  
        body.addEventListener('transitionend',plugRun);  
        body.addEventListener('mouseover',plugRun);
        body.addEventListener('mouseout',plugRun);
        body.addEventListener('mousedown',plugRun);
        body.addEventListener('mousemove',plugRun);//window.onmousedown  = J4Mousedown ;
        body.addEventListener('mouseup',plugRun);//window.onmousedown  = J4Mousedown ;
        //标准
        body.addEventListener('mousewheel',plugRun);//window.onmousewheel = J4Mousewheel;
        //IE注册事件
        if(document.attachEvent){
            document.attachEvent('onmousewheel',plugRun);
        } 
        //Firefox注册事件
        if(document.addEventListener){
            document.addEventListener('DOMMouseScroll',plugRun,false);
        } 
    });
    
})(); 

//初始化
window.onload = function(){
    if(!window.userInfo && J4.DEBUG){
        console.log("loginInfo");
        window.userInfo=J4.Json_decode(localStorage.getItem("userInfo"));
        window.userper=J4.Json_decode(localStorage.getItem("userper"));
    }
    initHtml();
    window.onresize=Resize;
    Resize();
    domReset(document.getElementsByTagName('body')[0]);
    J4._ready = true;
    J4.event('onload').run();
};
})();



//使用示例
//1、在首页中添加如下代码
/*
J4.ready(function(){
    J4.Require('account/test.mod',function(mod){
        mod.create("#app");
    });
});    
*/
//2、在test.mod中添加入如下js    
/*  J4({
        require:{ //依赖模块列表
            test2:'test2.mod',
        },
        //模块加载完成执行，this指向本对象即Module类对象
        onload:function(){ 
            
        },
        apiPath:null,//api接口基地址
        data:{}, //需要绑定的数据， 
        //实例化完成但是还没有初始化dom和数据,本方法后面的方法的this都指向Dom实例
        created:function(){ 
            
        },
        oninit:function(){ //dom和数据初始化以后
            
        },
        mounted:function(){ //节点插入

        },
        beforeUpdate:function(){ //数据更新前
            
        },
        updated:function(){ //数据更新后
            
        },
        beforShow:function(){//显示前
            
        },
        beforHide:function(){//显示后
            
        },
        beforeDestroy:function(){  //销毁前
            
        },
        destroyed:function(){ //销毁后
            
        },
        watch:function(name,value,beforvalue){ //数据更改后
            
        },
        methods:{  //挂载在this上面
            
            
        },
        computed:{//计算属性，绑定
            a:function(){return "a";}
        },
    });
*/

//3、插件使用示例

J4.Plugins({
    //test是插件名称
    test:{
        domInit:function(dom){
           //console.log('domInit',arguments);      
        },
        //change是监听的事件
        change:function(){
            console.log('test:change',arguments);
        },
    },
    accordion:{//手风琴菜单插件
        domInit:function(lineclass,dom){
            if(!lineclass){
                console.error('手风琴插件参数错误');
                return;
            }
            dom.eachChildren(lineclass,function(sdom){
                if(!sdom.nextElementSibling){
                    return false;
                }
                if(sdom.hasClass('accordion-show')){
                    sdom.nextElementSibling.show();
                }else{
                    sdom.nextElementSibling.hide();
                }
                return false;
            });
        },
        click:function(lineclass,dom,e){
            if(!lineclass){
                console.error('手风琴插件参数错误');
                return;
            }
            var cdom = null; 
            e.eachNode(lineclass,function(d){
                //d.addClass('accordion-show');
                cdom = d;
                return false;
            });
            if(!cdom){
               return;
            }
            dom.eachChildren(lineclass,function(sdom){
                if(!sdom.nextElementSibling){
                    return false;
                }
                if(cdom!=sdom){
                    sdom.removeClass('accordion-show');
                    sdom.nextElementSibling.hide();
                }else{
                    if(sdom.hasClass('accordion-show')){
                        sdom.removeClass('accordion-show');
                        sdom.nextElementSibling.hide();
                    }else{
                        sdom.addClass('accordion-show');
                        sdom.nextElementSibling.show();
                    }
                }
                return false;
            });
        }, 
    },
    clickshownext:{//手风琴菜单插件
        domInit:function(sdom){
            if(!sdom.nextElementSibling){
                return false;
            }
            if(sdom.hasClass('show-next')){
                sdom.nextElementSibling.show();
            }else{
                sdom.nextElementSibling.hide();
            }
            return false;
        },
        click:function(sdom,e){
            if(!sdom.nextElementSibling){
                return false;
            }
            if(sdom.hasClass('show-next')){
                sdom.nextElementSibling.hide();
                sdom.removeClass('show-next');
            }else{
                sdom.nextElementSibling.show();
                sdom.addClass('show-next');
            }            
        }, 
    },
});











